2011-11-07 50 views
2

我试着按照要求在查询中连接4个表。因为我想动态地在where子句中添加条件,所以,我现在可以为2表查询做到这一点。但是这4个表连接在这里是复杂的连接。为了延长我使用下面的代码的功能添加动态where子句:动态LINQ表达式查询,得到问题

public static class Extensions 
    { 
     public static IQueryable<T> AddEqualityCondition<T, V>(this IQueryable<T> queryable, 
      string propertyName, V propertyValue) 
     { 
      ParameterExpression pe = Expression.Parameter(typeof(T), "p"); 

    IQueryable<T> x = queryable.Where<T>(Expression.Lambda<Func<T, bool>>(Expression.Equal(Expression.Property(pe, typeof(T).GetProperty(propertyName)), Expression.Constant(propertyValue, typeof(V)), false, typeof(T).GetMethod("op_Equality")), new ParameterExpression[] { pe })); 
      return (x); 
     } 
    } 

// 我的代码添加这些条件:

Query is: 
var agrs = (from agr in _dbContext.Agreements 
           join amdv in _dbContext.AgreementMetaDataValues on agr.AgreementID equals amdv.AgreementID 
           join emd in _dbContext.EntityMetadatas on amdv.AttributeId equals emd.AttributeId 
           join et in _dbContext.Entities on agr.EntityID equals et.EntityId 
           select new agr, amdv,emd }); 

//Add dynamically where conditions: 
agrs = agrs.AddEqualityCondition("?????", "A83C82C5-F9D6-4833-A234-EBB5D971280C"); 

这是工作2表连接不超过那。因为在复杂的查询中它正在生成Annonymouse对象。所以 所以我需要通过什么来代替“??????”分数...?通常需要将属性名称作为“agr.AgreementId”传递,但这里它将扩展类中的表达式作为“Value Canot be Null:propertyName”引发。 需要此指导的更多指导...

+2

那岂不是更容易简单地使用:'AGRS = agrs.Where(X => x.agr.AgreementId ==“A83C82C5-F9D6-4833-A234- EBB5D971280C“);'? –

+1

我相信Marc的评论是答案,因为查询将在以后开始使用它的结果(例如遍历它们)时生成和执行。在此之前,您可以根据需要添加任意数量的where子句。 –

回答

5

我想你可能要考虑像(作为一个额外的过载):

public static IQueryable<T> AddEqualityCondition<T, V>(
    this IQueryable<T> queryable, 
    Expression<Func<T, V>> selector, V propertyValue) 
{ 
    var lambda = Expression.Lambda<Func<T,bool>>(
     Expression.Equal(
      selector.Body, 
      Expression.Constant(propertyValue, typeof(V)), 
      false, typeof(T).GetMethod("op_Equality")), 
     selector.Parameters); 
    return queryable.Where(lambda);   
} 

和使用:

agrs = agrs.AddEqualityCondition(x => x.agr.AgreementId, 
      "A83C82C5-F9D6-4833-A234-EBB5D971280C"); 
然而

!这是很容易,只需使用:

agrs = agrs.Where(x => x.agr.AgreementId == 
      "A83C82C5-F9D6-4833-A234-EBB5D971280C"); 
+0

这是完美的!多谢,伙计。以及如果我想获得基于x.agr.AgreementId的独特记录? –

+0

@Red你不能明确地得到“[某些成员]不同”,因为最终SQL并不真正支持这一点。如果这是** LINQ-to-Objects **,则可以**轻松地写入** DistinctBy,但如果这是LINQ-to-SQL或EF,则不能。如果你不希望有很多的蠢事,你可以通过本地获取并应用截然不同的东西。 –

+1

@Red一个基本的LINQ到对象实现可能如下所示:'public static IEnumerable DistinctBy (此IEnumerable 源,Func 选择器){var seen = new HashSet (); foreach(源中的var项)if(seen.Add(selector(item)))yield return item; }' –