如果不支持包含,您如何在 LINQ to Entities(实体框架)中执行 SQL 样式的“IN”语句?
Posted
技术标签:
【中文标题】如果不支持包含,您如何在 LINQ to Entities(实体框架)中执行 SQL 样式的“IN”语句?【英文标题】:How do you do a SQL style 'IN' statement in LINQ to Entities (Entity Framework) if Contains isn't supported? 【发布时间】:2010-09-24 14:57:48 【问题描述】:我正在使用 LINQ to Entities(不是 LINQ to SQL),但在创建“IN”样式查询时遇到了问题。这是我目前的查询:
var items = db.InventoryItem
.Include("Kind")
.Include("PropertyValues")
.Include("PropertyValues.KindProperty")
.Where(itm => valueIds.Contains(itm.ID)).ToList<InventoryItem>();
但是,当我这样做时,会引发以下异常:
LINQ to Entities 无法识别方法 'Boolean Contains(Int64)' 方法,并且该方法无法转换为存储表达式。
有人对此有解决方法或其他解决方案吗?
【问题讨论】:
valueIds
的类型是什么?
【参考方案1】:
你需要使用这个:
.Where(string.Format("it.ID in 0", string.Join(",", valueIds.ToArray())));
或动态构造 WHERE 部分,如 this 帖子中的。
附注- 信息已更新,此答案更新如下以保持相关性:
引用的链接包含以下更新:
...在 EF4 中,我们添加了对的支持 包含方法和至少在这个 collection-valued 的具体情况 参数。所以这种 代码现在可以开箱即用 而且没有必要使用任何 附加表达式构建方法:
var statusesToFind = new List<int> 1, 2, 3, 4;
var foos = from foo in myEntities.Foos
where statusesToFind.Contains(foo.Status)
select foo;
【讨论】:
我注意到,即使将 where 作为字符串传递,IN 也会被转换为许多 OR 语句.. @liggett78 由于自定义 ORM 不支持.Contains
或 .Any
,我现在面临这种情况。我正在尝试实现第一个解决方案,但我不确定它是如何工作的 - .Where
子句如何接受非函数参数?【参考方案2】:
在某些情况下,您可以使用 Linq 的 Any
扩展方法:
var userIds = new[] 1, 2, 3 ;
from u in Users
where userIds.Any(i => i==u.Id)
select u;
在这种情况下生成的 SQL 看起来很奇怪,但与许多 Linq-to-Entities 生成的 SQL 一样,它对人类来说可能过于冗长,但在实践中运行得很快。
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[DisplayName] AS [DisplayName],
FROM [dbo].[Users] AS [Extent1]
WHERE EXISTS (SELECT
1 AS [C1]
FROM (SELECT
[UnionAll1].[C1] AS [C1]
FROM (SELECT
1 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
UNION ALL
SELECT
2 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable2]) AS [UnionAll1]
UNION ALL
SELECT
3 AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable3]) AS [UnionAll2]
WHERE [UnionAll2].[C1] = [Extent1].[Id]
)
【讨论】:
【参考方案3】:正如 Diego B Vega 在 this post(第二个答案)中提到的,Contains
现在应该可以在 EF4 中使用。
【讨论】:
【参考方案4】:我的解决方法是将实体结果转换为应用 Contains() 的列表和 之后。
例子:
var items = db.InventoryItem
.Include("Kind")
.Include("PropertyValues")
.Include("PropertyValues.KindProperty")
.ToList()
.Where(itm => valueIds.Contains(itm.ID));
【讨论】:
太糟糕了,有时我真的很讨厌 EF 让你跳过去做事。但它适用,只是在代码中看起来很糟糕。谢谢 事实上,这种“解决方法”从数据库中获取所有数据并在 C# 中对其进行过滤。如果您有大量数据,它会有效地降低性能。 -1:您不想在应用附加过滤器之前对集合进行水合。以上是关于如果不支持包含,您如何在 LINQ to Entities(实体框架)中执行 SQL 样式的“IN”语句?的主要内容,如果未能解决你的问题,请参考以下文章
不支持 Linq-to-EF DateTime.ToLocalTime
Linq to EF 系统不支持异常 System.NotSupportedException
LINQ to SQL 或任何其他启用了 LINQ 的 ORM 是不是支持许多关联过滤?
如何修复 ApplicationUserManager 中的“LINQ to Entities 中不支持指定的类型成员‘UserId’”