Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
298 views
in Technique[技术] by (71.8m points)

c# - .NET Entity Framework - Using .Contains() to find a byte value in a Where expression

I am building an IQueryable based on parameters I get from the user. One of those parameters is a multi-select and I need to retrieve records that contain any of the selected values.

The code that deals with that is:

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

In the above code:
1. ids - is a byte array and I make sure it has multiple values before calling Contains().
2. c.CourseDeliveryID - that's a byte value.

In the database I store CourseDeliveryID as tinyint (SQL Server 2008).

Compilation is just fine.

When I run the code I get the following ArgumentException:
DbExpressionBinding requires an input expression with a collection ResultType.
Parameter name: input

I found the documentation for that exception here: http://technet.microsoft.com/en-us/library/system.data.common.commandtrees.expressionbuilder.dbexpressionbuilder.bindas.aspx

While trying to solve the problem I found that if I use the same code on shorts, ints or longs I don't have any problem.

I'm in touch with Microsoft about it since yesterday and will update when I know more, but in the meantime I figured I'd throw it also here to get more advises if possible.

Thanks in advance!

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I was able to reproduce your error in LINQPad, and found that using a List<byte> instead of a byte[] would work:

// 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));

will generate the following sql and return results:

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

It's also interesting that using an int[] or short[] would also work, producing this 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))

but using a byte[] causes an exception. I can only guess that the SQL Server EF provider is trying to treat byte[] in some special way, resulting in this exception.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...