【问题标题】:How to pass null in a string parameter placeholder如何在字符串参数占位符中传递 null
【发布时间】:2020-08-04 20:53:53
【问题描述】:

我有一个动态查询,我需要根据 URL 参数中传递的值构建它。 传递的值可以为 null 或带值。 在此示例中,参数是标题。 我正在使用带有 FromSql C# 函数的字符串参数占位符:

var query = this.BookContext.BookModel.FromSql(
            @"SELECT FROM Books b
            WHERE b.title = {0}, title)

如果标题有值,则查询可以正常工作,但是当标题为空时我会遇到问题。 当 title 为 null 时,条件应该是 b.title IS NULL 因为 b.title = NULL 不起作用。 我的问题是如何在字符串参数占位符中传递IS NULL 条件?

我尝试构建一个动态条件,但它不允许在字符串参数占位符中使用,这是有道理的,因为字符串参数占位符没有任何好处

string bookCondition = title != "null" ? title : "title IS NULL";

var query = this.BookContext.BookModel.FromSql(
            @"SELECT FROM Books b
            WHERE b.title {0}, bookCondition)

谢谢,

【问题讨论】:

  • 你真的不喜欢添加一个简单的 if 并构建两个不同的查询吗?
  • 这是一个包含多个条件的长查询。我刚刚发布了简短版本以简化我的问题。所以如果条件不是我正在寻找的选项
  • string bookCondition = title == null ? "IS NULL" : $"= '{title}'";
  • .FromSql(string.Format("SELECT FROM Books b WHERE b.title {0}", bookCondition)); BUT 你应该使用参数而不是像这样构建字符串,以避免sql注入。例如,如果title = "IS NULL; DROP TABLE [Books];--" 怎么办?那会很麻烦。见:Little Bobby Tables
  • 您可能需要更加仔细地思考这是否真的是您想要的行为。如果用户正在搜索一本书,但他们没有提供书名,这真的意味着他们想要查找没有书名的书吗?还是他们只是不在乎标题是什么?

标签: c# asp.net-core-2.2


【解决方案1】:

您不需要编写动态 SQL。我认为您应该使用 EF Core 提供的功能并尝试创建 linq 查询

var query = context.BookModel;

query = from book in query where book.Title == title select book;
// additional search criteria
if(author.HasValue) 
{
    query = from book in query where book.Author == author.Value select book;
}
// and so on
...
var items = await query.ToListAsync();

对于上面的示例,EF 将根据 title 参数值生成正确的 SQL 代码。

如果您确实需要动态 SQL,您可以使用 DbParameter 作为查询参数,但在这种情况下,您的代码将依赖于平台。

EF Core 3 的代码

var parameter = new SqlParameter("@t", SqlDbType.VarChar);
parameter.Value = title == null ? (object)DBNull.Value : (object)title;
var items1 = context.BookModel
    .FromSqlRaw("select * from Books b where (@t is null and b.title is null) or (b.title = @t)"), parameter);

EF Core 2.2 及更早版本有两个名为 FromSql 的方法重载,其行为方式与较新的 FromSqlRaw 和 FromSqlInterpolated 相同

【讨论】:

  • 这就是我想要的。谢谢你:)
  • 请注意,如果有问题的列被索引,这会破坏可搜索性。如果性能成为问题,您可能需要三思。
  • @Alejandro 那么你有更好的方法吗?什么是可搜索性?
  • @Alejandro 此谓词不影响性能,SQL Server 将使用索引
【解决方案2】:
    var items1 = null;
    if (title == null)
        items1 = context.BookModel.FromSqlRaw("select * from Books b where tile is null");
    else
    {
        var parameter = new SqlParameter("@t", SqlDbType.VarChar);
        parameter.Value = title;
        items1 = context.BookModel.FromSqlRaw("select * from Books b where tile = @t", parameter);
    }

【讨论】:

    猜你喜欢
    • 2020-09-30
    • 2021-03-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-30
    • 1970-01-01
    • 1970-01-01
    • 2018-11-17
    相关资源
    最近更新 更多