将LINQ中的表达式映射到sql抽象类



我有一个由两个类继承的抽象类。这两个类都表示数据库中的表。尽管在抽象类中映射表达式时遇到了问题,因此我不断收到无法将其转换为SQL的异常。我在Stackoverflow中发现的所有问题都是关于已经对我有效的列。

下面是一个非常简单的代码,展示了我的意思。汽车和摩托车具有完全独立的_isNew表达式实现。

public abstract class Vehicle  {
public abstract boolean IsNew;
}
public partial class Car: Vehicle {
public override boolean IsNew {
get { _isNew.Invoke(this); }
}
}
public partial class Motorcycle: Vehicle {
public override boolean IsNew {
get { _isNew.Invoke(this); }
}
}

我希望能够在IQueryable上调用_isNew表达式或isNew属性,但如果Vehicle是Car类型,它会运行Car类的_isNew。我有什么办法可以做到这一点吗?我尝试的所有解决方案都导致了一个无法转换为SQL的异常。

在我开始讨论您的问题之前,您可能应该查看一下关于异常的C#属性的最佳实践。

您可以急切地加载您的列表,然后调用IsNew属性,这将消除Linq-to-SQL错误。但我知道,如果您依赖IsNew来过滤其中的大量数据,这可能会导致性能问题。

我认为你的问题实际上是因为你想使用车辆的实例来获得"IsNew"属性。但是您根本无法做到这一点,因为当您尝试使用而不是映射到列的属性时,linq-to-sql会有理由抱怨。

那么,如果你不能使用一个实例,下一个最好的东西是什么

也许我会选择一个静态表达式

public partial class Motorcycle : Vehicle
{
public static Expression<Func<Vehicle, bool>> IsNew { get { return (v) => v.Age <= 1; } }
}
public partial class Car : Vehicle
{
public static Expression<Func<Vehicle, bool>> IsNew { get { return (v) => v.Age <= 2; } }
}

你可以像一样使用

var newCars = db.Cars.Where(Car.IsNew).ToList();
var newMotorcycles = db.Motorcycles.Where(Motorcycle.IsNew).ToList();

或者,您可以将逻辑拉到应用程序外部,并在SQL Server中将其作为计算列执行,我个人认为这是您的最佳选择。

抽象类允许您强制继承类来实现您的IsNew属性。它只是一个基类。你必须使用Car或Motorcycle的实现,为此,你应该将你的Vehicule对象投射为Car或摩托车,这样就会调用IsNew属性。

var vehicule = new Car();

最新更新