LINQ to Entities-使用条件where子句进行左外部联接

本文关键字:外部 子句 where Entities- to 条件 LINQ | 更新日期: 2023-09-27 17:57:53

我用EF4设置了这个项目,并使用LINQ to Entities来形成查询。

我在查询中遇到了一些问题,该查询涉及许多条件where子句和几个左外部联接。

我已经用下面的扩展方法(我在这里找到了)部分地解决了条件where子句。

public static IQueryable<TSource> WhereIf<TSource>(this IQueryable<TSource> source, bool condition, Expression<Func<TSource, bool>> predicate)
    {
        if (condition)
            return source.Where(predicate);
        else
            return source;
    }

我现在遇到的问题是,当我在联接表上使用扩展方法时,LINQ to Entities无法识别它。

以下是查询的一部分:

from p in context.Entities.OfType<Patient>()
    .WhereIf(!string.IsNullOrEmpty(name), p => p.Name.Contains(name))
from c in context.Contacts
    .Where(cp => cp.EntityID == p.EntityId).DefaultIfEmpty()
    .WhereIf(timestamp != null, c => c.Timestamp > timestamp)

我说部分解决了,因为它在这个查询中第一次(患者姓名)工作得很好,但第二次(时间戳)它给了我这个错误:

LINQ to Entities does not recognize the method 'System.Linq.IQueryable`1[x.Contact] WhereIf[Contact](System.Linq.IQueryable`1[x.Contact], Boolean, System.Linq.Expressions.Expression`1[System.Func`2[x.Contact,System.Boolean]])' method, and this method cannot be translated into a store expression.

所以,我想知道有没有人知道我该怎么解决这个问题?

LINQ to Entities-使用条件where子句进行左外部联接

问题是EF无法识别SelectMany中的WhereIf。将查询重写为方法语法会产生如下结果(查询不完整):

context.Entities.OfType<Patient>()
  .WhereIf(!string.IsNullOrEmpty(name), p => p.Name.Contains(name))
  .SelectMany(
    p => context.Contacts
      .Where(cp => cp.EntityID == p.EntityId).DefaultIfEmpty()
      .WhereIf(timestamp != null, c => c.Timestamp > timestamp),
    (p, c) => new { p, c }
  )

问题是最后一个WhereIf。您应该能够将其移动到SelectMany:之外

context.Entities.OfType<Patient>()
  .WhereIf(!string.IsNullOrEmpty(name), p => p.Name.Contains(name))
  .SelectMany(
    p => context.Contacts
      .Where(cp => cp.EntityID == p.EntityId).DefaultIfEmpty(),
    (p, c) => new { p, c }
  )
  .WhereIf(timestamp != null, x => x.c.Timestamp > timestamp)

您可以通过将查询强制转换为ObjectQuery并调用方法ToTraceString:来检查生成的SQL,看看您是否得到了真正想要的结果

var query = context.Entities.OfType<Patient>() ...
Console.WriteLine(((ObjectQuery) query).ToTraceString());

为什么不执行Where(timestamp == null || c.Timestamp > timestamp)