使用 Dapper 将项目列表(可能为空)作为 IN 子句的参数传递

Passing in a list of items (that can possibly be null) as params for an IN clause using Dapper

尝试使用 Dapper 将 NULL 项目列表作为参数传递时,出现 NULL 引用异常。通常在我的 where 子句中,我会简单地执行以下操作:

"AND (@Sections IS NULL OR Section IN @Sections)";

但我无法执行此操作,因为即使部分列表中有项目,它也不会工作。 Dapper 将它们添加为参数并且 (@sections1,@sections2 IS NULL OR) 将出错。如果我将我的部分列表保留为空,因为我不想将它用作过滤器,我会得到一个 NULL 引用异常。

我的函数必须有一个部分列表作为可选参数。这样,在我的代码中,我不必总是向我的查询添加部分过滤器。如何在我的函数参数中使部分成为可为 null 的列表,同时在 NULL 时也能与 Dapper 一起工作?

这是我的代码:

public static IEnumerable<Product> GetProformaFormularies(int? categoryId = null, IEnumerable<int> sections = null)
{
    using (var context = new AppContext())
    {
        var sql =
        "SELECT * " +
        "FROM Products " +
        "WHERE (@CategoryId IS NULL OR CategoryId = @CategoryId) " +
          "AND (Section IN @Sections)";

        return context.Database.Connection.Query<Product>(sql, 
        new { 
                CategoryId = categoryId,
                Sections = sections
            }).ToList();
    }
}

我想到的唯一解决方案是使用动态参数。还有比这更好的方法吗?

var sql =
    "SELECT * " +
    "FROM ProformaFormulary " +
    "WHERE (@CategoryId IS NULL OR CategoryId = @CategoryId) " +

if (sections != null)
{
    sql += " AND (Section IN @Sections)";
}

var parameters = new DynamicParameters();
parameters.Add("@CategoryId", categoryId);
if (sections != null)
{
    parameters.Add("@Sections", sections);
}

如果 sectionsnull,您可以省略 WHERE 子句的那部分:

var sql =
    "SELECT * " +
    "FROM Products " +
    "WHERE (@CategoryId IS NULL OR CategoryId = @CategoryId) ";

if (sections != null)
{
    sql += "AND (Section IN @Sections)"
}

return context.Database.Connection.Query<Product>(sql, 
    new { 
            CategoryId = categoryId,
            Sections = sections
        }).ToList();

如果不适用,dapper 似乎只会忽略您传递的对象上的 Sections 属性。

在我看来,代码中的 if 语句有时并不是您想要的。我有时只执行 .sql 个文件。所以唯一对我有用的就是这个。

var parameters = new
            {
                ApplySectionFilter = stringsToFilter != null,
                Sections = stringsToFilter 
            };

有一点开销,但最终更干净。在我看来。

SELECT * FROM Products
    WHERE (@ApplySectionFilter = 0 OR Section IN @Sections)