【问题标题】:.NET Entity Framework - Using .Contains() to find a byte value in a Where expression.NET Entity Framework - 使用 .Contains() 在 Where 表达式中查找字节值
【发布时间】:2011-04-11 21:17:03
【问题描述】:

我正在根据从用户那里获得的参数构建一个 IQueryable。其中一个参数是多选,我需要检索包含任何选定值的记录。

处理它的代码是:

var ids = parameters.DeliveryID.ToArray(); courses = courses.Where(c => ids.Contains(c.CourseDeliveryID));

在上面的代码中:
1. ids - 是一个字节数组,我在调用 Contains() 之前确保它有多个值。
2. c.CourseDeliveryID - 这是一个字节值。

在数据库中,我将 CourseDeliveryID 存储为 tinyint (SQL Server 2008)。

编译就好了。

当我运行代码时,我得到以下 ArgumentException:
DbExpressionBinding requires an input expression with a collection ResultType.
Parameter name: input

我在这里找到了该异常的文档: http://technet.microsoft.com/en-us/library/system.data.common.commandtrees.expressionbuilder.dbexpressionbuilder.bindas.aspx

在尝试解决问题时,我发现如果我在 short、int 或 long 上使用相同的代码,我没有任何问题。

我从昨天开始就这件事与 Microsoft 保持联系,当我知道更多信息时会更新,但与此同时,我想如果可能的话,我也会把它扔在这里以获得更多建议。

提前致谢!

【问题讨论】:

  • 打开您生成的 edmx 实体框架文件并查看 CourseDeliveryID 映射到的数据类型。也许它没有正确地将 tinyint 识别为字节。
  • @Milimetric - 非常感谢您的提示,但它没有帮助.. 我检查了 XML 定义文件,属性已正确映射并定义为字节:.

标签: c# .net linq entity-framework entity-framework-4


【解决方案1】:

我能够在 LINQPad 中重现您的错误,并发现使用 List<byte> 而不是 byte[] 会起作用:

// byte[] ids = new byte[] { 1, 64 };  <== causes ArgumentException
List<byte> ids = new List<byte> { 1, 64};

var c = Courses.Where (co => ids.Contains(co.CourseDeliveryId));

会生成如下sql并返回结果:

SELECT 
[Extent1].[CourseId] AS [CourseId], 
[Extent1].[CourseName] AS [CourseName], 
[Extent1].[CourseDeliveryId] AS [CourseDeliveryId]
FROM [dbo].[Courses] AS [Extent1]
WHERE [Extent1].[CourseDeliveryId] IN (1,64)

有趣的是,使用int[]short[] 也可以,生成这个sql:

SELECT 
[Extent1].[CourseId] AS [CourseId], 
[Extent1].[CourseName] AS [CourseName], 
[Extent1].[CourseDeliveryId] AS [CourseDeliveryId]
FROM [dbo].[Courses] AS [Extent1]
WHERE (1 =  CAST( [Extent1].[CourseDeliveryId] AS int)) OR (64 =  CAST( [Extent1].[CourseDeliveryId] AS int))

但使用byte[] 会导致异常。我只能猜测 SQL Server EF 提供程序正试图以某种特殊方式处理 byte[],从而导致此异常。

【讨论】:

  • 啊哈!好的。首先 - 非常感谢!!所以这是一种解决方法,但它受到支持并且有效,所以我想我们很好!正如我之前所说,我与 Microsoft 保持联系。我也会给他们发这个帖子,看看他们的想法。它确实闻起来像虫子,但谁知道呢.. 再次感谢!
  • @justabuzz,不客气;对我来说绝对看起来像一个错误。
  • 可能 byte[] 正在通过另一个代码路径,因为它是用于 varbinary、timestamp 等的类型。
  • DamienG 是完全正确的。这是我们在 EF 中遇到的一个问题,因为我们将 byte[] 映射到数据库中的二进制列,所以当我们在这个表达式中看到 byte[] 时,我们没有正确处理它。我们已经修复了 EF vNext。谢谢。
  • 这个问题在 EF 5 的最后一个版本中仍然存在,也许在 EF 6 中。我还没有回来查看 EF 6。
【解决方案2】:

虽然使用不同的容器可以解决问题,但您不必更改容器类型。 您需要做的就是将其分配给 IEnumerable:

IEnumerable<byte> ids = parameters.DeliveryID.ToArray();
courses = courses.Where(c => ids.Contains(c.CourseDeliveryID));

(在这种特定情况下,您可以只使用 ToList() 而不是 ToArray() 但在一般情况下,如果您获得字节数组并且不想将其重建为列表,则可以这样做)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-11
    • 2014-02-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多