SQL Server Express.Параметры не работают [дубликат]

Примером этого исключаемого исключения является: Когда вы пытаетесь проверить что-то, это null.

Например:

string testString = null; //Because it doesn't have a value (i.e. it's null; "Length" cannot do what it needs to do)

if (testString.Length == 0) // Throws a nullreferenceexception
{
    //Do something
} 

Время выполнения .NET исключение NullReferenceException при попытке выполнить действие над чем-то, что не было инстанцировано, т.е. код выше.

По сравнению с ArgumentNullException, которое обычно выбрано как защитная мера, если метод ожидает, что то, что происходит

Дополнительная информация находится в C # NullReferenceException и Null Parameter .

13
задан Mikhail Orlov 19 August 2010 в 17:35
поделиться

5 ответов

Параметры поддерживаются для операций DML, а не операций DDL, нет планов выполнения операций DDL. вам нужно будет использовать динамический SQL

DDL = язык определения данных (create, drop, alter ....)

DML = язык манипулирования данными (выберите, обновите, удалите, вставьте ) [/ д2]

16
ответ дан SQLMenace 27 August 2018 в 19:03
поделиться

Вы можете использовать только параметры в тех местах, где их поддерживает SQL Server. К сожалению, SQL Server не поддерживает параметризованные операторы CREATE DATABASE (хотя у меня есть чувство, что параметры файла могут содержать параметры файла.)

Вам нужно будет построить SQL самостоятельно: / g2]

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

ПРЕДОСТЕРЕЖЕНИЕ: это восприимчиво к атакам SQL-инъекций, поэтому следует принять меры предосторожности; если вы не доверяете источнику имени базы данных, не делайте этого!

Вам нужно будет внести аналогичные изменения в части имени файла, если они не могут быть параметризованы.

9
ответ дан Daniel Renshaw 27 August 2018 в 19:03
поделиться

Я решил эту проблему, создав метод расширения для надлежащего переноса всех объектов.

    /// <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);
0
ответ дан Justin 27 August 2018 в 19:03
поделиться

К сожалению, вы можете это сделать, завернув операцию DDL в операции DML.

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();
7
ответ дан Rich Hildebrand 27 August 2018 в 19:03
поделиться

Как немного сочетания ответа Даниила и Рича. Запустив DML-запрос к sp_executesql , вы можете получить динамически построенный запрос, также используя QUOTENAME , он должен избегать попыток в sql-инъекции, который кто-то может пройти.

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

Это должно выполнить следующий SQL-запрос DML с соответствующими переданными параметрами.

CREATE DATABASE [Demo]
       ON (FILENAME = @filename) 
       LOG ON (FILENAME = @filenamelog) 
       FOR ATTACH GO
3
ответ дан Scott Chamberlain 27 August 2018 в 19:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: