为什么这个短路不能在linq到sql查询中工作?

问题描述 投票:1回答:3

查询:

List<int> companyIds = null;

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

结果:

System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)中的System.Data.Linq.SqlClient.QueryConverter.VisitContains(表达式序列,表达式值)中的System.Linq.Enumerable.OnType.OnType。[TResult](IEnumerable source) System.Data.Linq.SqlClient.QueryConverter.VisitExpression(Expression exp)at System.Data.Linq.SqlClient.QueryConverter.VisitBinary(BinaryExpression b)at System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)at System System.Data.Linq.SqlClient.QueryConverter.VisitInner(Expression node)中System.Data.Linq.SqlClient.QueryConverter.VisitWhere(表达式序列,LambdaExpression谓词)的.Data.Linq.SqlClient.QueryConverter.VisitExpression(Expression exp)at at系统.Data.Linq.SqlClient.SqlProvider.System。 .Provider.IProvider.Execute(表达式查询)at EVaultSDK.Services.CompanyService.Get中的System.Data.Linq.DataQuery1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source)...

如果我添加ToList

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

有用

c# linq linq-to-sql
3个回答
2
投票

我认为原因是您正在使用LINQ to SQL,您的查询需要转换为SQL,并且在此转换发生时您会收到异常。 Contains在SQL中被翻译成IN运算符。但由于列表为null,我认为LINQ to SQL提供程序会抛出异常。

这就是为什么在ToList之后添加GetTable<Car>()时没有得到异常的原因,这会导致你在内存中获取并加载所有Cars,因此查询在内存上运行所以不需要转换为SQL和short - 电路按预期工作。

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

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


1
投票

你已经得到了一个很好的答案,为什么你得到错误 - 不是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();

-1
投票

试试这个。它将返回CompanyIds为null或包含car.CompanyID

return (from car in context.GetTable<Car>() 
        where companyIds == null || (companyIds != null && companyIds.Contains(car.companyID)) 
        select car)
        .ToList();
© www.soinside.com 2019 - 2024. All rights reserved.