как избежать ошибки с пустой переменной в подготовленном операторе

#c# #sql-server #asp.net-mvc

#c# #sql-сервер #asp.net-mvc

Вопрос:

         var publicFunctions = new PublicFunctionsController();

        if (!publicFunctions.CheckSession(Session["id"])) { RedirectToAction("Index", "Home"); };

        

        var src = DateTime.Now;
        var date = new DateTime(src.Year, src.Month, src.Day, src.Hour, src.Minute, 00);

        var arrow = OverUnder == "Over" ? $"EndTime >= {date}" : OverUnder == "Under" ? $"EndTime <= {date}" : "";
        var userCategories = Categoriesb == "" ? "" : $"Categories IN ({Categoriesb})";
        var lastId = $"Id > {Id}";
        var firstAnd = arrow == "" ? "" : "AND";
        var secondAnd = userCategories == "" ? "" : "AND";
        var sortByViews = ifViews == 1 ? "ORDER BY Views DESC" : "";

        //var strin = $"SELECT TOP 5 StatementTitle, Statement, ArgumentTitle, Argument, Explanation, Categories, EndTime, SessionId, Id FROM Statements WHERE {arrow} {firstAnd} {userCategories} {secondAnd} {lastId} ORDER BY Id DESC {sortByViews}";
        //the above works when used as query but below does not

        var queryString = "SELECT TOP 5 StatementTitle, Statement, ArgumentTitle, Argument, Explanation, Categories, EndTime, SessionId, Id FROM Statements WHERE @arrow @firstAnd @userCategories @secondAnd @lastId ORDER BY Id DESC @sortByViews";

        List<SingleStatementBlog> data = new List<SingleStatementBlog>();

        var con = publicFunctions.Connection();

        con.Open();

        SqlCommand command = new SqlCommand(queryString, con); //figure out or for like clause
        command.Parameters.AddWithValue("@arrow", arrow);
        command.Parameters.AddWithValue("@firstAnd", firstAnd);
        command.Parameters.AddWithValue("@userCategories", userCategories);
        command.Parameters.AddWithValue("@secondAnd", secondAnd);
        command.Parameters.AddWithValue("@lastId", lastId);
        command.Parameters.AddWithValue("@sortByViews", sortByViews);

        SqlDataReader reader = command.ExecuteReader();
        //error at first and
 

Когда я запускаю запрос с параметрами, я получаю сообщение об ошибке «ошибка при первом запуске», но когда я запускаю запрос без параметров, он работает (как видно из комментариев). Мне интересно, является ли пустая строка «» причиной сбоя…

Комментарии:

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

2. Мне не понадобится подготовленный оператор, если я проверяю значения перед раздачей, верно?

3. да, мне это не нужно, я не думаю, что это все новые значения, которые я создал.

4. Обратите внимание на правильный ответ dispose SqlConnection и Command с using блоками. Обратите внимание, что AddWithValue — это зло .

Ответ №1:

Вы не можете передавать операторы в качестве параметров в запрос, вместо этого передавая фактические значения.

Вы можете использовать StringBuilder для построения sql-запроса с параметрами на основе условий.

     var src = DateTime.Now;
    var date = new DateTime(src.Year, src.Month, src.Day, src.Hour, src.Minute, 00);

    var query = new StringBuilder();
    query.AppendLine(@"
      SELECT TOP 5 StatementTitle, Statement, ArgumentTitle, Argument
          , Explanation, Categories, EndTime, SessionId, Id 
      FROM Statements 
      WHERE 1 = 1");
    
    if (OverUnder == "Over")        
    {
        query.AppendLine("AND EndTime >= @date");
    }
    if (OverUnder == "Under")        
    {
        query.AppendLine("AND EndTime <= @date");
    }
    if (string.IsNullOrEmpty(Categoriesdb) == false)
    {
        query.AppendLine($"AND Categories IN ({Categoriesb})");
    }

    if (ifViews == 1)
    {
        query.AppendLine("ORDER BY Views DESC")
    }
    else
    {
        query.AppendLine("ORDER BY Id DESC")
    }

    using (var connection = createMyConnection())
    using (var command = new SqlCommand(query.ToString(), connection))
    {
        var param = new SqlParameter("@date", SqlDbType.DateTime) {Value = date};
        command.Parameters.Add(parameters);

        connection.Open();
        using (var reader = command.ExecuteReader())
        {
            // Read the data
        }
    }
 

Важно создать SqlParameter с правильными типами базы данных, это повысит производительность запроса и уменьшит возможные ошибки типа.

Обратите внимание, что при передаче Categoriesb вы все еще передаете «необработанные» данные в запрос.
Рассмотрите возможность использования табличных параметров

Комментарии:

1. Спасибо за один = один трюк … не могу поверить, что я не подумал об этом сначала!