构建动态where子句,Linq To Sql

时间:2011-12-16 21:24:22

标签: c# entity-framework entity-framework-4 linq-to-entities where-clause

我首先使用的是EF Code 4.2, 当where子句需要动态构建时,您建议使用什么样的解决方案? 然而,非常需要Include功能:

var results = db.Set<dynamicType>.Where("dynamic conditions").Include("....");

上面的动态条件需要查找到另一个表来过滤记录:  如果我想在Linq表达式中写出它,那就像是:

var result = db.Set<Contact>().Where(c=>c.AccountId == _Id_param || db.Set<LinkTable>().Any(a=>a.FkFieldId == c.AccountId && a.ParentId == _Id_param)).Include("Quotes");

我基本上需要上面表达式的动态linq,因为对于不同的类型,Where子句字段发生了变化(Contact只是一个例子),例如在一个Model中FK字段可能是“AccountId”而在另一个模型中它需要是“AccountFKId”。所以Where子句必须是动态的!

2 个答案:

答案 0 :(得分:3)

IQueryable是可组合的,因此您可以动态构建查询:

var query = db.Set<Contact>().Include(...);

if (something) 
{
    query = query.Where(...);
}

// Other wheres

Linq是强类型的,因此您至少必须知道在Set<>电话中您要开始使用哪种类型。您可以将其设为通用但不是动态的(除非您要通过反射将其全部写出来)。

您可以使用dynamic linq来定义包含字符串的条件,但至少您必须知道Set<>的类型。

答案 1 :(得分:1)

<强>更新

我能够通过直接修改表达式树来解决问题。

使用来自TomasP's blog的想法有很多帮助:

关键是为内部查询创建第二个IQueryable,然后将其作为表达式传递给现有动态模型的IQueryable表达式。

IQueryable<LinkTable> linkQuery = db.Set<LinkTable>().AsQueryable();

MethodCallExpression internalQueryWhere = Expression.Call(typeof(Queryable), "Where", new Type[] { linkQuery.ElementType }, linkQuery.Expression,Expression.Lambda<Func<LinkTable, bool>>(myfilters, new ParameterExpression[] { filterParameter })); 

linkQuery = linkQuery.Provider.CreateQuery<LinkTable>(internalQueryWhere);

Expression anyMethodExpr = Expression.Call(typeof(Queryable), "Any", new Type[] { linkQuery.ElementType }, linkQuery.Expression);

现在您可以将anyMethodExpr传递给原始Entity的IQueryable where子句。