Byr*_*ahl 5 c# inheritance entity-framework
我有以下类型:
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; }
}
Run Code Online (Sandbox Code Playgroud)
我有一个代码优先的DBContext:
public MyDbContext: DbContext {
public DbSet<Car> Cars { get; set; }
public DbSet<Motorcycle> Motorcycles { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果我直接查询汽车或摩托车,这很有用...
var dbContext = new MyDbContext();
var cars = dbContext.Set<Car>().Where(x=> x.TopSpeed>10); // <-- THIS WORKS
Run Code Online (Sandbox Code Playgroud)
但如果我想要所有车辆清单,无论是汽车还是摩托车,我都想这样做:
var dbContext = new MyDbContext();
var vehicles = dbContext.Set<Vehicle>().Where(x=> x.TopSpeed>10); // <-- THIS DOES NOT WORK
Run Code Online (Sandbox Code Playgroud)
当我尝试上面的代码时,我得到一个例外:
System.InvalidOperationException:实体类型Vehicle不是当前上下文的模型的一部分.
这很有道理......我没有将Vehicle添加到上下文中.我加了汽车和摩托车.在这一点上,我不知道该怎么做.我尝试将Vehicle添加到我的上下文中,但是将car和moto的表合并到一个Vehicle表中.我当然想要一个单独的汽车和摩托车桌子(也可能是车辆基座属性的桌子).最好的方法是什么?
Shy*_*yju 11
Vehicle在MyDbContext类中有一个类型为DBSet的Vehicles属性.
public MyDbContext: DbContext {
public DbSet<Car> Cars { get; set; }
public DbSet<Motorcycle> Motorcycles { get; set; }
public DbSet<Vehicle> Vehicles { set; get; }
}
Run Code Online (Sandbox Code Playgroud)
现在您可以使用这样的标准访问所有车辆
var vehicles = dbContext.Set<Vehicle>().Where(x=> x.TopSpeed>10);
Run Code Online (Sandbox Code Playgroud)
请记住,您的实体类(ID或{ClassName}ID)中应该有一个Key Property .否则它会给你一个运行时错误!(是的,代码将编译.)
public abstract class Vehicle
{
public int ID { set; get; }
public double TopSpeed { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
编辑:根据评论
默认情况下,实体框架将执行每个层次结构的表.层次结构中的所有数据都保存在单个表中,并使用该Discriminator列来标识哪个记录属于哪个子类型.因此,作为结果,您将拥有一个Vehicle表,其列与层次结构中所有类的属性相同,并带有一个名为" Discriminator" 的额外列.对于Car for Record,它将在Discriminator列中包含"Car"值.

如果要为每种类型创建单个表,我们将选择Table Per Type.实体框架将为所有子类的基类和单独表创建一个表.
要实现此目的,您可以使用Fluent API覆盖配置.
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<Car>().ToTable("Cars");
modelBuilder.Entity<Motorcycle>().ToTable("Motorcycles");
base.OnModelCreating(modelBuilder);
}
Run Code Online (Sandbox Code Playgroud)
输出是

现在您应该能够像这样查询您的车辆参赛作品
var vehicles = dbContext.Set<Vehicle>().Where(x => x.TopSpeed > 150).ToList();
Run Code Online (Sandbox Code Playgroud)
结果就在这里

请注意,结果包含MotorCycle类型和Car类型.
检查此链接以确定要使用的继承策略.