模块化(重构)Linq查询

本文关键字:Linq 查询 重构 模块化 | 更新日期: 2023-09-27 18:06:36

我有一些Linq查询。语义上,它们是

    a join b join c join d where filter1(a) &&filter2 (c),,filter3 (d)

  1. a join b join c where filter1(a) &filter2 (c)

  2. a join b join c join e where filter (a) &&filter2 (c),,filter4 (e)

我希望能够提出共享部分:

a join b join c where filter1(a) && filter2(c)

并动态追加join dfilter3(d)

有办法做到这一点吗?我已经使用谓词生成器来动态构建条件(过滤器)。

编辑:我正在使用Linq-to-SQL。

编辑:基本查询如下:

from a in As.AsExpandable()
join b in Bs on a.Id equals b.PId
join c in Cs on b.Id equals c.PId
where filter1(a) && filter2(b) && filter3(c)
select new A { ... }

过滤器是谓词生成器中的谓词。查询类型为"IQueryable<A>"。

接下来,我想用d

from a in BaseQuery()
join d in D on a.Id equals d.PId

当前join d ..导致编译错误:

连接子句中一个表达式的类型不正确。调用Join

时类型推断失败

模块化(重构)Linq查询

您的示例有点模糊,但是很容易创建一个返回IQueryable<T>的方法并重用该方法,如果这就是您的意思。下面是一个例子:

// Reusable method
public IQueryable<SomeObject> GetSomeObjectsByFilter(Context c)
{
     return
         from someObject in context.SomeObjects
         where c.B.A.Amount < 1000
         where c.Roles.Contains(r => r.Name == "Admin")
         select someObject;
}

你可以在其他地方重用这个方法,像这样:

var q =
    from c in GetSomeObjectsByFilter(context)
    where !c.D.Contains(d => d.Items.Any(i => i.Value > 100))
    select c;

由于IQueryable的工作方式,只有最后的查询(开始迭代的集合)才会触发对数据库的调用,这允许您通过重用在数据库内有效执行的业务逻辑来构建高度可维护的系统,从而消除任何性能损失。

我一直这样做,这大大提高了我代码的可维护性。无论您运行哪种O/RM工具,它都可以工作,因为在一个和平中编写查询或将其拆分为不同的方法之间,Queryable<T>组成没有区别。

请注意,您有时确实需要一些智能转换来在单个方法中获得重复部分。可能有帮助的是返回分组集合,以及返回与您认为需要的类型不同的集合。这听起来有点空洞,但只要在这里张贴一个问题,当你有问题分裂一个方法。这里有足够多的人可以帮助你。

你的问题我可以轻松回答一半。Linq使得在现有查询中附加。where子句变得很简单。

的例子:

var x = db.Table1.where(w => w.field1 == nTestValue);
x = x.where(w => w.field2 == nTestValue2);

我相信你也可以做连接,但我必须在一些旧代码中找到一个例子。