简体   繁体   English

LINQ 到实体 - 带有条件 where 子句的左外连接

[英]LINQ to Entities - Left outer join with a conditional where clause

I have this project set up with EF4 and I'm using LINQ to Entities to form queries.我已经使用 EF4 设置了这个项目,并且我正在使用 LINQ 到实体来形成查询。

I'm having some trouble with a query that involves lots of conditional where clauses and several left outer joins.我在涉及大量条件 where 子句和几个左外连接的查询时遇到了一些问题。

I have partially solved the conditional where clauses with the following extension method (which I found here ).我已经使用以下扩展方法(我在此处找到)部分解决了条件 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;
    }

The problem I have now is that LINQ to Entities doesn't recognize the extension method when I use it on the joined tables.我现在遇到的问题是,当我在连接表上使用扩展方法时,实体的 LINQ 无法识别扩展方法。

Here's a part of the query:这是查询的一部分:

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)

I say partially solved because it works just fine the first time (patient name) in this query, but the second time (timestamp) it gives me this error:我说部分解决了,因为它在此查询中第一次(患者姓名)工作得很好,但第二次(时间戳)它给了我这个错误:

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.

So, I'm wondering if anyone know how I can fix this?所以,我想知道是否有人知道我该如何解决这个问题?

The problem is that EF is unable to recognize WhereIf inside a SelectMany .问题是 EF 无法识别SelectMany中的WhereIf Rewriting your query into method syntax yields something like this (query is incomplete):将查询重写为方法语法会产生类似这样的结果(查询不完整):

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 }
  )

The problem is the last WhereIf .问题是最后一个WhereIf You should be able to move it outside the SelectMany :您应该能够将其移到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)

You can inspect the resulting SQL to see if you get what you actually want by casting the query into ObjectQuery and calling the method ToTraceString :您可以通过将查询转换为ObjectQuery并调用ToTraceString方法来检查生成的 SQL 以查看您是否得到了真正想要的结果:

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

Why not do Where(timestamp == null || c.Timestamp > timestamp) ?为什么不做Where(timestamp == null || c.Timestamp > timestamp)

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

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