在Linq语句的Where子句中,
var myClasses = (from b in db.MyRecords
join p in db.People on b.PersonId equals p.PersonId
join cse in db.Courses on b.CourseId equals cse.CourseId
where (b.Active == 1)
select new { b });
表达式b.Active==1
运行良好。但如果我这样做,
Expression<Func<MyRecords, bool>> filter = my => my.Active == 1;
[更新:由于Hans的回答,我保留了原来的答案,但实际上,我在这里打错了。表达式实际上使用的是底层类型,而不是像查询Linq那样EF生成的复数。我实际上有这个,
Expression<Func<MyRecord, bool>> filter = my => my.Active == 1;
]
试试这个,
var myClasses = (from b in db.MyRecords
join p in db.People on b.PersonId equals p.PersonId
join cse in db.Courses on b.CourseId equals cse.CourseId
where (filter)
select new { b });
编译器抱怨,
无法将查询表达式转换为预期的委托类型,因为块中的个返回类型不能隐式转换为委托返回类型
我看到了很多关于这个的SO问题,但我不明白为什么它不起作用。我误解了基本原理,所以我并没有真正要求任何人编写代码。我想知道林克想要什么,这样我对林克有了更好的了解,而不仅仅是让一些东西发挥作用。例如,
var myClasses = (from b in db.MyRecords.Where(filter)
join p in db.People on b.PersonId equals p.PersonId
join cse in db.Courses on b.CourseId equals cse.CourseId
select new { b });
我想知道为什么它在那里有效,而在加入后的Where中无效。如果我在联接结束时执行Where,编译器仍然知道MyRecords字段,包括Active。
我认为这就是我想要的正确描述,因为它似乎很适合我。
http://www.albahari.com/nutshell/linqkit.aspx
您的过滤器只是第一个示例中应用的类型错误。blue-linq语法为您提供了很多神奇的功能,使该查询易于阅读。实际情况是创建一些匿名类型,其中包含对项目的引用。请注意,在where子句中,还可以使用p
和cse
变量。当你把它考虑到你的表达式中时,你可能会认为它像这个Expression<Func<Tuple<MyRecords, People, Courses>>
,实际上它不是一个元组,而是一些匿名类型。
当你要求重新arper将蓝色语法转换为方法链时,它会生成这样的代码:
(db.MyRecords.Join(
db.People,
b => b.PersonId,
p => p.PersonId,
(b, p) => new {b, p})
.Join(
db.Courses,
t => t.b.CourseId,
cse => cse.CourseId,
(t, cse) => new {t, cse})
.Where(t => (t.t.b.Active == 1))
.Select(t => new {t.t.b}));
实际上,你不能像以前那样在蓝色语法中使用过滤变量:
... join cse in db.Courses on b.CourseId equals cse.CourseId
where (filter)
您必须切换到方法调用:
(from b in db.MyRecords
join p in db.People on b.PersonId equals p.PersonId
join cse in db.Courses on b.CourseId equals cse.CourseId
select b)
.Where(filter)
现在,因为我们将内部查询修剪为仅b
,所以您可以应用过滤器。