繁体   English   中英

如何在Join之后的两个表的Where子句中为Linq创建Lambda表达式?

[英]How can I create an Lambda Expression for Linq in the Where clause for two tables after the Join?

我有这个,

 Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
 Func<MyCourse, bool> funcWhere = filter.Compile();

然后这个

var myClasses = db.MyCourse.Join(db.People, mc => mc.PersonId, 
p => p.PersonId, (mc, p) => new { MyCourse= mc, Person = p }).Where(???)

之所以需要这样做,是因为如果我首先将过滤器放在MyCourse表上,

db.MyCourse.Where(funcWhere).Join....

创建的SQL将带回所有人员和所有MyCourse,然后使用过滤器。 如果我在最后做

(mc, p) => new { MyCourse= mc, Person = p }).Where(mc=>mc.MyCourse.Active == 1)

我对Joins有很好的查询。 否则,引擎首先将所有行查询到内存中。 具有数千行的两个独立查询。

我已经在SO和其他地方看到了很多与此相关的问题。 我找不到一个告诉我如何使用动态Where Expression<Func<T,TResult>>从Join中创建多个表的Where Expression<Func<T,TResult>>

目的是根据表达式(而不是Dynamic Linq ,并且没有第三方)来创建动态查询语句。实际上,该问题声称“ Where”结尾处较慢,但在我的程序中它使用Joins进行了正确的查询。

MyCourse具有一个PersonId,而People具有一个PersonId。 如果我亲手写的话,

select mc.CourseName, p.LastName 
from MyCourse mc inner join Person p on mc.PersonId = p.PersonId
where mc.Active = 1;

(这些只是问题的示例列。它们不是我在上述查询中真正想要的,除了Active ==1。)

使用Lambda表达式中的Join子句

更新:FWIW,我能够在此上运行它,

    var param = Expression.Parameter(typeof(MyClass), "MyClassDebug");
    var exp = Expression.Lambda<Func<MyClass, bool>>(
        Expression.Equal(
            Expression.Property(param, dbParameter),
            Expression.Constant(dbValue)
        ),
        param
    );

我没有导航属性或其他任何内容。 我可以这样使用它

var MyQuery = (from recs in dbcontext.MyClass.Where(exp)
               ...three joins

产生的SQL看起来不错,并且Explain计划显示了最少的行检索。

我怀疑在您的Expression上调用Compile()会造成麻烦。 您的完整查询包括Join ,但是您已经编译了Where子句,因此它无法编译包括Join Together的整个查询。 这可能就是为什么它要抓住整个表的原因,因为它首先自己执行Where ,然后再执行Join

但是您不需要调用Compile() 只需将Expression传递到Where()

Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
var myClasses = db.MyCourse
    .Where(filter)
    .Join(db.People, mc => mc.PersonId, 
p => p.PersonId, (mc, p) => new { MyCourse= mc, Person = p }).ToList();

某种程度上与您的实际问题无关,但是如果您创建了外键,则可以稍微简化一下。 如果尚未更新模型,请在Visual Studio项目中进行更新。 您的Person类将更改为具有MyCourse的列表,而您的MyCourse类将具有Person的列表。

因此,您可以执行以下操作:

Expression<Func<MyCourse, bool>> filter = mc => mc.Active == 1;
var courses = db.MyCourse.Include("Person").Where(filter);
foreach (var course in courses) {
    var person = course.Person; //This is populated with the Person record
}

Linq处理MyCourse ,并且返回的每个MyCourse都将具有Person属性。

暂无
暂无

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

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