Почему это короткое замыкание не работает в запросе linq to sql? - PullRequest
0 голосов
/ 14 сентября 2018

Запрос:

List<int> companyIds = null;

(from car in context.GetTable<Car>()
where companyIds == null || companyIds.Contains(car.companyID)
select car)
.ToList();

Результат:

в System.Linq.Enumerable.OfType [TResult] (источник IEnumerable) в System.Data.Linq.SqlClient.QueryConverter.VisitContains (последовательность выражений, значение выражения) в System.Data.Linq.SqlClient.QueryConverter.VisitInner (узел выражения) в System.Data.Linq.SqlClient.QueryConverter.VisitExpression (выражение Expression) в System.Data.Lq.SqlClient.QueryConverter.VisitBinary (BinaryExpression b) в System.Data.Linq.SqlClient.QueryConverter.VisitInner (узел выражений) в System.Data.Linq.SqlClient.QueryConverter.VisitExpression (выражение Explay.InClient. В системе.QueryConverter.VisitWhere (последовательность выражений, предикат LambdaExpression) в System.Data.Linq.SqlClient.QueryConverter.VisitInner (узел выражений) в System.Data.Linq.SqlClient.QueryConverter.ConvertOuter (узел выражений) в System.Data.LinCl..SqlProvider.BuildQuery (запрос выражения, аннотации SqlNodeAnnotations) в System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute (запрос выражения) в System.Data.Linq.DataQuery 1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() at System.Collections.Generic.List 1..ctor (источник IEnumerable 1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable 1) в EVaultSDK.Services.CompanyService.Get ...

Если я добавлю ToList

 context.GetTable<Car>().ToList()

Это работает

Ответы [ 3 ]

0 голосов
/ 14 сентября 2018

Попробуй это.Он вернет CompanyIds, ноль или содержит car.CompanyID

return (from car in context.GetTable<Car>() 
        where companyIds == null || (companyIds != null && companyIds.Contains(car.companyID)) 
        select car)
        .ToList();
0 голосов
/ 14 сентября 2018

У вас уже есть хороший ответ о том, почему вы получаете ошибку - не все в C # хорошо переводятся в SQL, и вы часто не узнаете об этом до времени выполнения.

На всякий случай, если в будущем посетительв ответ на этот вопрос в поисках обходного пути. Я бы предложил использовать тот факт, что вы можете создать запрос, и он не будет извлекать какие-либо данные, пока вы не вызовете ToList() (или Single() и т. д.):

List<int> companyIds = null;

var query = context.GetTable<Car>();
if (companyIds != null)
    query = query.Where(car => companyIds.Contains(car.companyID));

var result = query.ToList();
0 голосов
/ 14 сентября 2018

Я думаю, причина в том, что вы используете LINQ to SQL, ваш запрос должен быть переведен в SQL, и вы получите исключение во время этого перевода.Contains переводится в оператор IN в SQL.Но так как список пуст, я думаю, что поставщик LINQ to SQL выдает исключение.

Это причина, по которой вы не получаете исключение при добавлении ToList после GetTable<Car>(), это заставляет васизвлекать и загружать все Cars в память, поэтому запрос выполняется в памяти, поэтому нет необходимости переводить его в SQL, и короткое замыкание работает, как и ожидалось.

Обычно, если вы вызываете Contains напустой список, вы должны получить NullReferenceException, но вы получите ArgumentNullException.Поэтому вам следует проверить трассировку стека, и, если это так, не использовать нулевой список в вашем запросе.

Редактировать: отправленная вами трассировка стека подтверждает мое предположение.Где-то вдоль дороги в списке вызывается метод OfType, который вызывает исключение.

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