.NET Entity Framework - Использование .Contains () для поиска значения байта в выражении Where - PullRequest
19 голосов
/ 12 апреля 2011

Я строю 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.<br> Parameter name: input

Я нашел документацию для этого исключения здесь: http://technet.microsoft.com/en-us/library/system.data.common.commandtrees.expressionbuilder.dbexpressionbuilder.bindas.aspx

Пытаясь решить проблему, я обнаружил, что если я использую один и тот же код для шорт, целых или длинных, у меня не возникает никаких проблем.

Со вчерашнего дня я нахожусь в контакте с Microsoft и сообщу об этом, когда узнаю больше, но в то же время я решил, что добавлю и сюда, чтобы получить больше советов, если возможно.

Заранее спасибо!

Ответы [ 2 ]

27 голосов
/ 12 апреля 2011

Я смог воспроизвести вашу ошибку в 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[] особым образом, что приводит к этому исключению.

2 голосов
/ 14 июня 2015

Хотя использование разных контейнеров решает проблему, вам не нужно менять тип контейнера.Все, что вам нужно сделать, это присвоить его IEnumerable:

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

(В этом конкретном случае вы можете просто использовать ToList () вместо ToArray (), но в общем случае, если вы получаете байтовый массив и делаетене хочу перестраивать его как список, это будет делать)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...