为什么这种短路在linq to sql查询中不起作用?

时间:2018-09-14 16:19:04

标签: c# linq linq-to-sql

查询:

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(表达式exp)      在System.Data.Linq.SqlClient.QueryConverter.VisitBinary(BinaryExpression b)      在System.Data.Linq.SqlClient.QueryConverter.VisitInner(表达式节点)      在System.Data.Linq.SqlClient.QueryConverter.VisitExpression(表达式exp)      在System.Data.Linq.SqlClient.QueryConverter.VisitWhere(表达顺序,LambdaExpression谓词)      在System.Data.Linq.SqlClient.QueryConverter.VisitInner(表达式节点)      在System.Data.Linq.SqlClient.QueryConverter.ConvertOuter(表达式节点)      在System.Data.Linq.SqlClient.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()

有效

2 个答案:

答案 0 :(得分:2)

我认为原因是您使用的是LINQ to SQL,您的查询需要转换为SQL,并且在转换发生时会收到异常。 Contains在SQL中转换为IN运算符。但是由于列表为空,所以我认为LINQ to SQL提供程序会引发异常。

这就是为什么在ToList之后添加GetTable<Car>()时没有得到异常的原因,这导致您获取并加载内存中的所有Cars,因此查询运行在内存上,因此不需要将其转换为SQL,并且短路可以按预期进行。

通常,如果您在空列表中调用Contains,您应该会得到NullReferenceException,但您会得到ArgumentNullException。因此,您应该检查堆栈跟踪,如果是这种情况,请不要在查询中使用空列表。

编辑:您发布的堆栈跟踪确认了我的假设。在列表中调用OfType方法的某个地方,它会导致异常。

答案 1 :(得分:-1)

尝试一下。它将返回CompanyIds为null或包含car.CompanyID

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