繁体   English   中英

实体框架核心 Lambda Function 未提前终止

[英]Entity Framwork Core Lambda Function not early terminating

我正在使用带有实体框架的 asp.net 内核。

在进行 API 调用以获取实体列表时,我在 json 中传递了一个可选过滤器,该过滤器可能如下所示:

{
  "name": "john",
  "customer.id": 1
}

在我的 ControllerAction 中,我首先反序列化 JSON,然后查询数据库。

var dynamicfilter = filter != null ? JsonConvert.DeserializeObject<Dictionary<string, string>>(filter) : new Dictionary<string, string>();

List<User> Users = _context.Users.Include(u => u.Customer).Where(u =>
    dynamicfilter.Keys.Count > 0 ? (
        (dynamicfilter.ContainsKey("name") ? u.Name.ToLower().Contains(dynamicfilter["name"].ToLower()) : true) &&
        (dynamicfilter.ContainsKey("customer.id") ? u.Customer.ID == Convert.ToInt32(dynamicfilter["customer.id"]) : true)
    ) : true).ToList();

只要设置了所有过滤器参数,它就可以工作。 如果未设置至少一个过滤器参数,则会抛出 null 引用,因为即使ContainsKey()false ,代码之间的代码是什么? 和:被执行。

但是如果我首先加载整个表并在本地应用过滤器,通过这样做

List<User> Users = _context.Users.Include(u => u.Customer).ToList().Where(...

它就像一个魅力。 有没有办法让它在数据库端也能工作?

只需将逻辑移出查询即可。 喜欢:

IQueryable<User> query = _context.Users.Include(u => u.Customer);
query = dynamicfilter.ContainsKey("name") 
    ? query.Where(u=>u.Name.ToLower().Contains(dynamicfilter["name"].ToLower()) 
    : query;
query = dynamicfilter.ContainsKey("customer.id") 
    ? query.Where(u=>u.Customer.ID == Convert.ToInt32(dynamicfilter["customer.id"])) 
    : query;

List<User> Users = query.ToList(); // DB query executed here

这样,表达式树将在query object 中构建,并且仅在尝试枚举时执行。 检查 MS 文档

此接口继承了 IEnumerable 接口,因此如果它表示一个查询,则可以枚举该查询的结果。 枚举强制执行与 IQueryable object 关联的表达式树。 调用 Execute(Expression) 方法时会执行不返回可枚举结果的查询。

最重要的是,我建议在将其应用于查询之前检查所有传入参数

if(dynamicfilter.ContainsKey("name") 
    && !string.IsNullOrWhitespace(dynamicfilter["name"]))
{
    var nameFilter = dynamicfilter["name"].ToLower();
    query = query.Where(u=>u.Name.ToLower().Contains(nameFilter);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM