5

我有以下类型:

public abstract class Vehicle {
    public int Id { get; set; }
    public double TopSpeed { get; set; }
}

public class Car : Vehicle {
    public int Doors { get; set; }
}

public class Motorcycle : Vehicle { 
    public string Color { get; set; }
}

我有一个代码优先的 DBContext:

public MyDbContext: DbContext { 
    public DbSet<Car> Cars { get; set; }
    public DbSet<Motorcycle> Motorcycles { get; set; }
}

如果我直接查询汽车或摩托车,这非常有用......

var dbContext = new MyDbContext();
var cars = dbContext.Set<Car>().Where(x=> x.TopSpeed>10); // <-- THIS WORKS

但是,如果我想要所有车辆的列表,无论是汽车还是摩托车,我想这样做:

var dbContext = new MyDbContext();
var vehicles = dbContext.Set<Vehicle>().Where(x=> x.TopSpeed>10); // <-- THIS DOES NOT WORK

当我尝试上面的代码时,我得到一个异常:

System.InvalidOperationException :实体类型 Vehicle 不是当前上下文模型的一部分。

这很有意义......我没有将 Vehicle 添加到上下文中。我添加了汽车和摩托车。在这一点上,我不知道该怎么办。我尝试将 Vehicle 添加到我的上下文中,但这会将 car 和 moto 的表合并到一个 Vehicle 表中。我绝对想要一个单独的汽车和摩托车表(可能还有一个用于车辆基础属性的表)。最好的方法是什么?

4

3 回答 3

11

Vehicle在 MyDbContext 类中有一个 DBSet 类型的车辆属性。

public MyDbContext: DbContext { 
    public DbSet<Car> Cars { get; set; }
    public DbSet<Motorcycle> Motorcycles { get; set; }
    public DbSet<Vehicle> Vehicles { set; get; }
}

现在您可以使用这样的条件访问所有车辆

var vehicles = dbContext.Set<Vehicle>().Where(x=> x.TopSpeed>10);

请记住,您的实体类(ID{ClassName}ID)中应该有一个键属性。否则它会给你一个运行时错误!(是的,代码将编译。)

public abstract class Vehicle
{
    public int ID { set; get; }
    public double TopSpeed { get; set; }
}

编辑:根据评论

默认情况下,实体框架将为每个层次结构创建一个表。层次结构中的所有数据都保存在一个表中,并使用该Discriminator列来识别哪个记录属于哪个子类型。因此,您将拥有一个 Vehicle 表,其列与层次结构中所有类的属性相同,并带有一个名为“ Discriminator”的额外列。对于 Car 的记录,它将在 Discriminator 列中具有“Car”值。

在此处输入图像描述

如果您想为每种类型创建单个表,我们将选择每个类型的。实体框架将为基类创建一个表,并为所有子类创建一个单独的表。

为此,您可以使用 Fluent API 覆盖配置。

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Car>().ToTable("Cars");
        modelBuilder.Entity<Motorcycle>().ToTable("Motorcycles");

        base.OnModelCreating(modelBuilder);
    }

输出是

在此处输入图像描述

现在您应该可以像这样查询您的车辆条目

 var vehicles = dbContext.Set<Vehicle>().Where(x => x.TopSpeed > 150).ToList();

结果就在这里

在此处输入图像描述

请注意,结果同时包含MotorCycle类型和Car类型。

检查此链接以确定要使用的继承策略。

于 2012-05-02T19:24:25.630 回答
0

您是否尝试过仅使用 DBSet 为 Vehicle 提供自己的上下文?我认为这可能对你有用。

于 2012-05-02T19:44:05.547 回答
0

在继承的类上使用 DataAnnotation.Schema.Table("TableName") 条目会触发为继承类型(每个类型的表)创建新表并消除父类型表中的鉴别器字段,而无需需要 Fluent API 代码。

于 2012-07-24T14:27:41.670 回答