使用动态LINQ对子查询进行过滤

本文关键字:查询 过滤 动态 LINQ | 更新日期: 2023-09-27 18:14:52

我正在开发一个使用动态LINQ库进行过滤的大型应用程序。

我的数据访问层中的所有类都派生自一个共同的祖先DALAncestor,该祖先定义了GetData方法:

一个Customer的这个方法的实现看起来像这样(简化):

public override List<Entities.Customer> GetData(Filter filter) {
  var customers = from c in db.Customers
                  select new Entites.Customer { 
                    ID = c.ID,
                    FullName = c.Name,
                    Country = c.Country
                  };
   return = filter.Apply(customers).ToList();
}

"Apply"是一个方法,它接受一组条件,并使用动态LINQ库应用所有条件。

方法GetData是这样调用的:

private void DemoCallGetDataMethod() {
  var filter = new Filter();
  filter.AddCondition("Country", "Austria");
  var list = myCustomerDAL.GetData(filter);
  // do something
}
SQL Server得到一个select语句:

SELECT [t0].ID, [t0].Name, [t0].Country
  FROM Customer [t0]
 WHERE [t0].Country = @p0

(@p0是一个参数,其值设置为"Austria")。

一切都很好,如果我只想过滤"顶部"(主)级别的值。但是,由于我在过滤器表单上根据用户的输入构建过滤器,因此在某些情况下,用户希望按详细级别的值进行过滤(即,只有在用户单击"Search"之后才知道要过滤的列)。

我找不到解决方案:"找到所有购买百事可乐的奥地利客户"。

我尝试了几种方法,但似乎都不起作用。其基本思想是:
1. 为DynamicLibrary添加CONTAINS支持
2. 将我的代码改为

public override List<Entities.Customer> GetData(Filter filter) {
  var customers = from c in db.Customers
                  select new Entites.Customer { 
                    ID = c.ID,
                    FullName = c.Name,
                    Country = c.Country,
                    Items = c.Order.SelectMany(o => o.Item).Select(i => i.ItemId).ToList()
                  };
  return = filter.Apply(customers).ToList();
}
private void DemoCallGetDataMethod() {
  var filter = new Filter();
  filter.AddCondition("Country","=", "Austria");
  filter.AddCondition("Items","Contains", "11"); // 11 = Id for Pepsi
  var list = myCustomerDAL.GetData(filter);
  // do something
}

抛出的异常是:

系统。InvalidOperationException:没有泛型方法'Contains'在类型'System.Linq上。Enumerable'与提供的类型参数和参数兼容。如果方法是非泛型的,则不应提供类型参数。

有人知道我做错了什么吗?或者我只是走错了方向,我应该尝试其他方法?哪个?:)

编辑:改变我的例子

使用动态LINQ对子查询进行过滤

@user182630我希望能够根据子选择中的值进行过滤一般来说,不只是针对特定的案例。那篇文章中的方法只有当你硬编码你的过滤器时才有效,这不是我能做到的做的。- Marko juvan 9 mins ago

通读这篇文章http://csharpindepth.com/articles/chapter5/closures.aspx

我在应用程序中使用PredicateBuilder进行动态查询。

谓词建设者

在你的情况下,我想它会是这样的:

 string MyCountry = "Austria";
 string MyProductId = 11
 var Predicate = PredicateBuilder.True<db.Customers>();
 Predicate = Predicate.And(p=>p.Country ==MyCountry && p.Order.SelectMany(o=>o.Item).Where(i=>i.id == 11).Count() >0);
 var list = Customers.Where(Predicate).Select(s=>s).ToList();