实体框架-链接到实体-可选过滤器

本文关键字:实体 过滤器 链接 框架 | 更新日期: 2023-09-27 18:16:49

我正在努力弄清楚如何在单个语句中获得LINQ语句以在SQL中生成特定的WHERE子句。

我想让它产生如下内容:

SELECT ColA, ColB, ColC, ColN...
FROM Orders
WHERE Client = @ClientId
AND (@CompanyId IS NULL OR @CompanyId = CompanyId)

My (failing) LINQ语句如下:

var includeAllCompanies = company == null;
var data = context.Orders.Where(o => o.Client.Id == clientId
           && (includeAllCompanies 
                 || (c.Company != null && c.Company.Id == company.Id)).ToList();

然而,当变量company为NULL时,它总是抛出异常(当它被初始化时,它工作得很好)。例外是:

Non-static method requires a target.

我当前的修复是将我的LINQ语句分成两个。一个使用Expression<Func<>>(将被转换为具有部分过滤的SQL语句)。然后另一个使用Func<>对返回的列表执行剩余的过滤器。

Expression<Func<>>让SQL做一些工作(不包括可空对象)

var data = context.Orders.Where(o => o.Client.Id == clientId).ToList();

Func<>然后过滤掉可为空的对象

data = data.Where(c => (territory == null 
       || (c.Territory != null && c.Territory.Id == territory.Id))).ToList();

这个可以工作,但是,我希望SQL执行这个查询。

实体框架-链接到实体-可选过滤器

问题是,company是服务器端变量。不管includeAllCompanies的值,EF必须将整个LINQ查询转换为SQL -在这种情况下,SQL不知道company.Id是什么-所以EF必须始终获得company.Id的值,以便放入SQL查询。即使company是空的(这就是为什么你得到异常)。我希望你明白我的意思,如果不明白,我将试着给一些样品。

为了摆脱异常,你可以这样做:

var companyId = company == null ? null  : (int?)company.Id;
var data = context.Orders.Where(o => o.Client.Id == clientId
           && (companyId  == null
                 || (c.Company != null && c.Company.Id == companyId)).ToList();