Linq to Entities 添加 Where 子句以在另一个表中查找 EXISTS

Posted

技术标签:

【中文标题】Linq to Entities 添加 Where 子句以在另一个表中查找 EXISTS【英文标题】:Linq to Entities add Where clause for EXISTS lookup in another table 【发布时间】:2012-05-15 19:48:53 【问题描述】:

使用 Linq to Entities,我有一个 IQueryable<T> 并想向它添加另一个 WHERE 子句,它等效于 SQL 中的 EXISTS 子句。我不需要实际从另一个表中提取任何数据,只需检查是否满足条件即可过滤结果。这是我最近的尝试:

IQueryable<FileEntity> files = repository.Files.Where(...);
// More stuff done to files

files = files.Where(f => repository.FileInfo.Where(i => i.Foo == "bar")
                                            .Select(i => t.FileId)
                                            .Contains(f => f.FileId));
var list = files.ToList(); // ERROR!

我也尝试过:

files = files.Where(f => repository.FileInfo.Any(i => i.FileId == f.FileId));

任何情况下的例外是 ol'“无法创建类型为 'FileInfo' 的常量值。在此上下文中仅支持原始类型('例如 Int32、String 和 Guid')。”

如何在数据库服务器上实现这种类型的查询?

【问题讨论】:

感谢您在第二个示例中发布错误消息。你也可以为第一个做吗? @Mark - 两种情况下的错误完全相同。当你调用类似ToList 的东西来执行查询时,就会抛出异常。 是来自 DB 的 FileInfo 实体还是只是一个类?如果它不是实体 - 您可以在每个 FileInfo 条目的循环中执行此操作。 供参考:msdn.microsoft.com/en-us/library/bb896317.aspx,请参阅不支持引用非标量变量 @Val - FileInfo 是一个实体,一个IQueryable&lt;FileInfo&gt;,最终是一个DbSet&lt;FileInfo&gt;,来自与Files相同的上下文 【参考方案1】:
IQueryable<FileEntity> files = repository.Files.Where(...);
// More stuff done to files
var ids = repository.FileInfo.Select(i=>i.FileId).ToList();

var list = files.Where(f => ids.Contains(f.FileId)).ToList();

【讨论】:

【参考方案2】:

嗯,一种选择是使用连接:

files = files.Join(repository.FileInfo.Where(i => i.Foo == "bar"),
                   f => f.FileId,
                   i => i.FileId,
                   (f, i) => f)
             .Distinct();

我不认为这一定会转化为 SQL 中的 EXISTS 查询,但看看查询计划,它很可能正在做同样的事情......

【讨论】:

谢谢,这很有帮助。它似乎在工作,但让 SQL 真的、真的、真的很讨厌。 (几乎是原来的三倍。) @DaveMateer:但这如何转化为查询执行计划的变化?您接受的解决方案(两个查询)需要从数据库中获取数据,然后将其传递回它 - 如果您最终会得到很多匹配的文件,这可能会非常痛苦。也许在您的特定情况下这不是问题,但值得考虑。 您的观察是正确的,这就是我的情况有所不同的因素。我希望“伪存在”查询平均只返回几条记录。这可能是一种清洗性能,但另一种解决方案对我来说似乎更直观,希望对维护代码的人来说更直观!恐怕几个月后我会忘记,“为什么我要进行联接,预测结果以消除联接表,然后得到不同的记录?”我仍然希望 Linq to Entities 中有一个实际的、真正的“EXISTS”选项,但我想这不是一个选项。 供参考:使用 EF Core 2.0,此答案会生成一个简短易读的 SQL 语句。

以上是关于Linq to Entities 添加 Where 子句以在另一个表中查找 EXISTS的主要内容,如果未能解决你的问题,请参考以下文章

分组后的LINQ to Entities,COUNT和WHERE不起作用

Linq to Entities 中的动态 where 子句 (OR)

LINQ to Entities Perf优化

Linq to Entities基础之需要熟知14个linq关键字(from,where,select,group,let,on,by...)

Linq TO Entities Exists 和 contains 之间的区别

在 LINQ to Entities 查询中无法构造实体或复杂类型