我有一个包含标签对象集合的任务对象...在数据库中,表称为任务和标签。
有多种方法可以搜索任务,因此使用 LINQ,我在表达式树中构造我的 LINQ 查询...类似于下面的代码示例:
IQueryable<Data.Task> query = ctx.DataContext.Tasks;
if (criteria.Number > 0)
query = query.Where(row => row.Number == criteria.Number);
if (criteria.CustomerId != Guid.Empty)
query = query.Where(row => row.Project.CustomerId == criteria.CustomerId);
if (criteria.ProjectId != Guid.Empty)
query = query.Where(row => row.ProjectId == criteria.ProjectId);
var data = query.Select(row => TaskInfo.FetchTaskInfo(row));
this.AddRange(data);
这很好用……但现在我想搜索具有特定标签的任务,例如会计或功能请求。
我可以通过完整的查询在 LINQPad 中执行此操作:
from t in Tasks
join l in Labels on t.TaskId equals l.SourceId
where l.Name == "accounting"
select t
有没有办法使用表达式树来做到这一点?我卡住了!任何帮助将不胜感激!
最佳答案
查询表达式中的“join”(不是“join ... into”)子句转换为 Join 调用。棘手的一点是透明标识符 - 只有一个序列来自连接,并且它必须同时包含 t
和 l
(在你的例子中)所以编译器会一些魔法。
我没有太多时间在这里详细介绍,但最好只向您展示您的查询表达式是如何翻译的。
这个:
from t in Tasks
join l in Labels on t.TaskId equals l.SourceId
where l.Name == "accounting"
select t
翻译成:
Tasks.Join(Labels, t => t.TaskId, l => l.SourceId, (t, l) => new { t, l })
.Where(z => z.l.Name == "accounting")
.Select(z => z.t)
请注意此处“z”的引入 - 基本上包含原始表达式中的 t 和 l。
编辑:David Morton 的回答提供了一种更有效的方法。他的行相当于:
from t in Tasks
join l in (from x in Labels where x.Name == "accounting")
on t.TaskId equals l.SourceId
select t
如果连接后只有一个 select 子句,编译器可以跳过透明标识符并将投影直接作为最后一个参数传递给连接调用。
关于c# - 如何在 LINQ 的表达式树中创建连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/485398/