【问题标题】:Mapping expressions in LINQ-to-sql abstract classLINQ-to-sql 抽象类中的映射表达式
【发布时间】:2016-10-03 22:07:52
【问题描述】:

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

下面是一个非常简单的代码,说明了我的意思。 Car 和 Motorcycle 对 _isNew Expression 有完全独立的实现。

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 的异常。

【问题讨论】:

  • 什么是_isNew? Can't 是 可以 被翻译的表达式吗?
  • _isNew 是一个可以翻译成 SQL 的表达式(例如对于汽车 Expression> _isNew = (v) => v.Age > _isNew = (v) => v.Age
  • 我想这根本行不通,因为要调用您对 IsNew 的覆盖,将需要 Car 或 Motorcycle 的具体实例。因此,EF 必须先查询项目才能创建这些实例。
  • 什么是确切的错误信息?
  • @Sami 如果您的问题包含导致错误的语句,那就太好了。

标签: c# .net linq inheritance .net-3.5


【解决方案1】:

抽象类允许你强制继承的类来实现你的 IsNew 属性。它只是一个基类。 您必须使用 Car 或 Motorcycle 的实现,为此,您应该将 Vehicule 对象转换为 Car 或 Motorcycle,以便调用正确的 IsNew 属性。

var vehicule = new Car();

【讨论】:

  • 问题是关于映射到数据库和父抽象类的两个类的 linq-to-sql 转换。它不仅仅是一个普通的继承/抽象类。
【解决方案2】:

在我回答你的问题之前,你应该检查一下best practices of C# properties concerning exceptions

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

我认为您的问题实际上是由于您想使用车辆的实例来获取“IsNew”属性。但是你根本不能这样做,因为 linq-to-sql 会合理地抱怨 when you are trying to use a property that is not mapped to a column

如果您不能使用实例,下一个最好的方法是什么?

也许我会选择静态表达式

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 中作为 computed column 执行,我个人认为这是您的最佳选择。

【讨论】:

  • 感谢您的回答。我对你的提议的主要问题是我并不总是知道类型,所以我最终会在很多地方添加 typeof 并在运行 IsNew 表达式之前进行转换。我得出的结论是,我根本无法单独使用 LINQ,但设法找到了一个有点肮脏的解决方法:我使用了 LINQKit ExpandableQuery 并扩展了整个逻辑以选择正确的表达式。这样,Vehicle 类永远不会发送到 LINQ,只有 Car 和 Motorcycle 会在那里处理。虽然不是一个非常干净的解决方案
  • 我非常同意你关于计算列、存储过程、视图在 SQL Server 中处理所有内容的观点。但我正在处理一个现有的大型项目,其中所有表达式都已在 LINQ 中定义。重写这些需要几个月的时间,因此最好找到一种 LINQ 方法。
  • 我忍不住觉得反射可以在某种程度上帮助你,这是 C# 的一个非常令人困惑的方面,如果你还没有使用它的经验,可能不是时候使用效率高。虽然我个人发现像这样的棘手结构问题通常可以通过反思来解决。
猜你喜欢
  • 2010-11-23
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 2010-12-28
  • 2017-10-23
  • 1970-01-01
  • 2010-11-26
相关资源
最近更新 更多