2010-08-19 9 views
13

इसे छोटा करने के लिए।पैरामीटर डीबी नाम के साथ डाटाबेस बनाने के लिए SqlCommand का उपयोग कैसे करें?

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; 
    } 

यह ठीक कार्यान्वित:: मैं दो सरल सहायकों मिल गया है

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(); 

लेकिन यह नहीं करता है:

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(); 

क्यों?

उत्तर

13

पैरामीटर डीएमएल संचालन के लिए समर्थित हैं डीडीएल संचालन नहीं, डीडीएल संचालन के लिए कोई निष्पादन योजना नहीं है। आप (...., ड्रॉप बनाने के लिए, परिवर्तन) गतिशील एसक्यूएल का उपयोग करने के

DDL = डेटा परिभाषा भाषा की आवश्यकता होगी

DML = डेटा हेरफेर भाषा (, चयन अद्यतन, हटाने, डालने)

+0

वास्तव में सवाल का जवाब नहीं है, रिच हिल्डब्रैंड का बेहतर जवाब है। –

9

आप केवल उन स्थानों पर पैरामीटर का उपयोग कर सकते हैं जहां SQL सर्वर उनका समर्थन करता है। दुर्भाग्य से SQL सर्वर पैरामीटरयुक्त CREATE DATABASE कथन का समर्थन नहीं करता है (हालांकि मुझे फ़ाइल नाम समर्थन पैरामीटर महसूस हो रहा है)।

आप एसक्यूएल खुद के निर्माण के लिए की आवश्यकता होगी:

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(); 

चेतावनी: इस एसक्यूएल इंजेक्शन हमलों इसलिए लिया जाना caremust करने के लिए susceptable है; यदि आप डेटाबेस नाम के स्रोत पर भरोसा नहीं करते हैं, तो ऐसा मत करो!

यदि आपको या तो पैरामीटर नहीं किया जा सकता है तो आपको फ़ाइल नाम भागों में समान परिवर्तन करने की आवश्यकता होगी।

+0

आपके उत्तर के लिए धन्यवाद! –

7

दुख की बात है आप इसे डीएमएल ऑपरेशन में अपने डीडीएल ऑपरेशन को लपेटकर पूरा कर सकते हैं।

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

हालांकि ऐसा लगता है कि यह दृष्टिकोण एसक्यूएल इंजेक्शन (जो पैरामीटर का उपयोग करता है) के खिलाफ सुरक्षा प्रदान करता है, यह नहीं है! –

3

डैनियल और रिच के जवाब दोनों के संयोजन के रूप में। sp_executesql को कोई DML क्वेरी चलाने करके आप एक गतिशील बनाया क्वेरी हो सकता है, यह भी QUOTENAME का उपयोग करके इसे एसक्यूएल इंजेक्शन किसी पर किसी भी प्रयास में पास कर सकते हैं बच चाहिए।

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(); 

यह उचित साथ निम्नलिखित DML एसक्यूएल क्वेरी को निष्पादित करना चाहिए पैरामीटर पारित किया।

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

क्या असेंबली का निर्माण कमांड का हिस्सा है? क्या यह .NET 45 – user1591131

+0

@ user1591131 CreateComand में उपलब्ध है, यह प्रश्न इस पृष्ठ के शीर्ष पर प्रश्न में लिखा गया है। –

0

मैंने सभी इकाइयों को उचित रूप से लपेटने के लिए एक विस्तार विधि बनाकर इस समस्या को हल किया।

/// <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(); 
    } 

उपयोग:

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); 
संबंधित मुद्दे