为什么这个Linq-to-SQL查询在执行Where子句时不强制转换对象?

本文关键字:转换 对象 子句 Where Linq-to-SQL 查询 执行 为什么 | 更新日期: 2023-09-27 18:10:51

我有一个类似于下面的Linq查询,

var dataByWheels = this.Db.Cars.Cast<IVehicle>().Where(v => (v.NumWheels == 4));

IVehicle在这种情况下是一个接口,它定义了类必须具有NumWheels属性。Cars类类似如下,

[Table]
public class Car : IVehicle
{
     [Column]
     public double Weight { get; set; }
     ...
     public int NumWheel 
     {
         get { return 4; }
     }
}

所以在这种情况下,NumWheels属性不存储在数据库中,但是如果转换完成,那么它应该是好的。但是会引发异常,

The member 'MyProject.IVehicle.NumWheels' has no supported translation to SQL

表示不执行强制转换。当我在Cast之后插入ToList()到链中时,它确实工作,但我认为这是过早地解决查询并创建整个表的巨大列表,并且希望避免,因为我正在电话上工作。

我做错了什么?

(注意,我更改了名称和查询,使其更简单)

为什么这个Linq-to-SQL查询在执行Where子句时不强制转换对象?

发生这种情况是因为当您对LINQ to SQL类发出Where语句时,LINQ to SQL引擎期望您直接对数据库执行WHERE语句,并试图将该语句映射到原始的T-SQL,因为NumWheels不是数据库列。

为了克服这个问题,您可以先对它执行ToList,但要注意这样做对性能的影响。这段代码将循环遍历整个Cars表,并在内存中进行过滤。然而,我想不出别的方法来实现你的目标。

var dataByWheels = this.Db.Cars.ToList().Where(v => (v.NumWheels == 4));

问题不在于您的LINQ,而在于您的使用上下文。这个特定的LINQ查询正在Queryable上使用,并且Cast将强制它到DB并在那时拉回所有结果。然后,您可以对可枚举对象进行强制转换并继续,但它很可能不是您在本例中所要寻找的。

该错误仅仅表明您编写了一个表达式,该表达式不能映射到SQL并在SQL服务器上执行。这是EF的事情,而不是LINQ的事情。