2010-08-19 20 views
13

Kısa süreliğine. Bu Tamam yürütürSqlCommand parametreli db adı ile CREATE DATABASE nasıl kullanılır?

private SqlCommand CreateCommand(string text) 
    { 
     SqlCommand cmd = new SqlCommand(); 
     cmd.Connection = connection; 
     cmd.CommandType = CommandType.Text; 
     cmd.CommandText = text; 
     return cmd; 
    } 

    void SetParameter(SqlCommand cmd, string p, string dbName) 
    { 
     cmd.Parameters.Add(p, SqlDbType.NVarChar); 
     cmd.Parameters[p].Value = dbName; 
    } 

: İki basit yardımcıları var

var cmd = CreateCommand("CREATE DATABASE Demo "+ 
      @"ON (FILENAME = N'c:\demo_data.mdf') "+ 
      @"LOG ON (FILENAME = N'c:\demo_data.mdf.LDF') "+ 
      "FOR ATTACH " + 
      "GO"); 
cmd.ExecuteNonQuery(); 

Ama bu değil:

string dataBaseAttachText = "CREATE DATABASE @dbname " + 
           "ON (FILENAME = @filename) " + 
           "LOG ON (FILENAME = @filenamelog) " + 
           "FOR ATTACH GO"; 
var cmd = CreateCommand(dataBaseAttachText); 

SetParameter(cmd, "@dbname", "Demo"); 
SetParameter(cmd, "@filename", @"c:\demo_data.mdf"); 
SetParameter(cmd, "@filenamelog", @"c:\demo_data.mdf.LDF"); 

cmd.ExecuteNonQuery(); 

Neden?

cevap

13

DDL işlemleri değil, DML işlemleri için parametreler desteklenir, DDL işlemleri için yürütme planı yoktur. Eğer (.... değiştirmek, damla oluşturun) dinamik SQL

DDL = veri tanımlama dili kullanmak

DML = Veri İşleme Dili (seçin güncelleme, silme, ekleme) Ne yazık ki

+0

sorunun cevabı değil, Zengin Hildebrand'ın daha iyi bir cevabı var. –

9

Sadece SQL Server'ın bunları desteklediği yerlerde parametreleri kullanabilirsiniz. Ne yazık ki, SQL Server parametrelenmiş CREATE DATABASE ifadelerini desteklemiyor (her ne kadar dosya adı destek parametrelerine sahip olabilirim).

Sen SQL kendiniz inşa etmek gerekir:

string dataBaseAttachText = "CREATE DATABASE [" + dbName + "] " + 
           "ON (FILENAME = @filename) " + 
           "LOG ON (FILENAME = @filenamelog) " + 
           "FOR ATTACH GO"; 
var cmd = CreateCommand(dataBaseAttachText); 

SetParameter(cmd, "@filename", @"c:\demo_data.mdf"); 
SetParameter(cmd, "@filenamelog", @"c:\demo_data.mdf.LDF"); 

cmd.ExecuteNonQuery(); 

DİKKAT: Bu yüzden alınacak caremust SQL enjeksiyon saldırıları susceptable olduğu; Veritabanı adının kaynağına güvenmiyorsanız, bunu yapma!

Eğer dosya adı parametrelerine dönüştürülemiyorsa, dosya adı bölümlerinde de benzer değişiklikler yapmanız gerekir.

+0

Cevabınız için teşekkür ederiz! –

7

gerekecektir DDL işleminizi bir DML işleminde sarmalayarak bunu başarabilirsiniz. Bir ikisi Daniel kombinasyonu ve Rich'in cevabın biraz itibariyle

var createDatabaseQuery = "exec ('CREATE DATABASE ' + @databaseName)"; 

var sqlCommand = new SqlCommand(createDatabaseQuery, sqlConnection); 
sqlCommand.Parameters.Add("@databaseName", SqlDbType.Text); 
sqlCommand.Parameters["@databaseName"].Value = "HelloWorld"; 

sqlCommand.ExecuteNonQuery(); 
+0

Bu yaklaşım gibi görünüyor görünüyorsa, SQL enjeksiyonuna karşı koruma sağlar (parametreleri kullanarak), o değil! –

3

. sp_executesql bir DML sorgu çalıştırarak bunu geçebildiği SQL Injection Birine her türlü girişimi kaçış gerektiğini de QUOTENAME kullanarak, dinamik yapılı sorgu olabilir.

string dataBaseAttachText = @" 
DECLARE @SQLString nvarchar(500); 
DECLARE @ParmDefinition nvarchar(500); 
SET @SQLString = 
    N'CREATE DATABASE ' + QUOTENAME(@dbName) + N' 
     ON (FILENAME = @filename) 
     LOG ON (FILENAME = @filenamelog) 
     FOR ATTACH GO' 
SET ParmDefinition = N'@filename nvarchar(MAX), @filenamelog nvarchar(MAX)' 
EXECUTE sp_executesql @SQLString, @ParmDefinition, @filename = @filename, @filenamelog = @filenamelog"; 

var cmd = CreateCommand(dataBaseAttachText); 

SetParameter(cmd, "@dbname", "Demo"); 
SetParameter(cmd, "@filename", @"c:\demo_data.mdf"); 
SetParameter(cmd, "@filenamelog", @"c:\demo_data.ldf"); 

cmd.ExecuteNonQuery(); 

Bu doğru ile aşağıdaki DML sql sorgusu çalıştırmak gerekir parametreler geçti.

CREATE DATABASE [Demo] 
     ON (FILENAME = @filename) 
     LOG ON (FILENAME = @filenamelog) 
     FOR ATTACH GO 
+0

CreateCommand'ın bir parçası nedir? Kullanılabilir .net 45 – user1591131

+0

@ user1591131 CreateComand, bu sayfanın en üstünde yazılı olan bir sorudur. –

0

Tüm varlıkları uygun şekilde sarmak için bir uzantı yöntemi oluşturarak bu sorunu çözdüm.

/// <summary> 
    /// Quotes the provided string in a sql friendly way using the standard [ and ] characters 
    /// </summary> 
    /// <param name="ObjectName">string to quote</param> 
    /// <example> 
    /// "mytable".QuoteSqlName() would return [mytable] 
    /// "my[complex]table".QuoteSqlName() would return [my[[complex]]table] 
    /// </example> 
    /// <returns>quoted string wrapped by quoting characters</returns> 
    /// <remarks>For dynamic sql this may need to be called multiple times, one for each level of encapsulation.</remarks> 
    public static string QuoteSqlName(this string ObjectName) 
    { 
     return ObjectName.QuoteSqlName(']'); 
    } 

    /// <summary> 
    /// Quotes the provided string in a sql friendly way using the provided character 
    /// </summary> 
    /// <param name="ObjectName">string to quote</param> 
    /// <param name="QuoteCharacter">Character to quote with, use [ or ] for standard sql quoting</param> 
    /// <example> 
    /// "mytable".QuoteSqlName() would return [mytable] 
    /// "my[complex]table".QuoteSqlName() would return [my[[complex]]table] 
    /// "justin's computer".QuoteSqlName('\'') would return 'justin''s computer' 
    /// </example> 
    /// <returns>quoted string wrapped by quoting characters</returns> 
    public static string QuoteSqlName(this string ObjectName, char QuoteCharacter) 
    { 
     return ObjectName.QuoteSqlName(QuoteCharacter, false); 
    } 

    /// <summary> 
    /// Quotes the provided string in a sql friendly way using the provided character 
    /// </summary> 
    /// <param name="ObjectName">string to quote</param> 
    /// <param name="QuoteCharacter">Character to quote with, use [ or ] for standard sql quoting</param> 
    /// <param name="IsNvarChar">if true and QuoteCharacter is ' will prefix the quote with N e.g. N'mytable' vs 'mytable'</param> 
    /// <example> 
    /// "mytable".QuoteSqlName() would return [mytable] 
    /// "my[complex]table".QuoteSqlName() would return [my[[complex]]table] 
    /// "justin's computer".QuoteSqlName('\'') would return 'justin''s computer' 
    /// "mytable".QuoteSqlName('\'',false) would reutrn 'mytable' 
    /// "mytable".QuoteSqlName('[',true) would return [mytable] 
    /// "mytable".QuoteSqlName('\'',true) would reutrn N'mytable' 
    /// </example> 
    /// <returns>quoted string wrapped by quoting characters</returns> 
    public static string QuoteSqlName(this string ObjectName, char QuoteCharacter, bool IsNvarChar) 
    { 
     if (string.IsNullOrEmpty(ObjectName)) 
      return ObjectName; 

     char OtherQuoteCharacter = (char)0; 
     bool UseOtherChar = false; 
     if (QuoteCharacter == ']' || QuoteCharacter == '[') 
     { 
      QuoteCharacter = '['; 
      OtherQuoteCharacter = ']'; 
      UseOtherChar = true; 
     } 

     var sb = new StringBuilder((int)(ObjectName.Length * 1.5) + 2); 
     if (QuoteCharacter == '\'' && IsNvarChar) 
      sb.Append('N'); 

     sb.Append(QuoteCharacter); // start with initial quote character 
     for (var i = 0; i < ObjectName.Length; i++) 
     { 
      sb.Append(ObjectName[i]); 
      // if its a quote character, add it again e.g. ] becomes ]] 
      if (ObjectName[i] == QuoteCharacter || UseOtherChar && ObjectName[i] == OtherQuoteCharacter) 
       sb.Append(ObjectName[i]); 
     } 
     sb.Append(UseOtherChar ? OtherQuoteCharacter : QuoteCharacter); // finish with other final quote character 

     return sb.ToString(); 
    } 

Kullanımı:

var QuotedDBName = this.DBName.QuoteSqlName(); 
CreateDBQuery.AppendFormat("USE {0};", QuotedDBName); 
CreateDBQuery.AppendFormat("IF TYPE_ID({0}) IS NULL", DBType.Name.QuoteSqlName('\'', true)); 
CreateDBQuery.AppendFormat(" CREATE TYPE {0} as {1};", DBType.Name.QuoteSqlName(), DBType.Value); 
İlgili konular