[英]Querying by base type in EF4 Code-First
我有以下類型:
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表中。 我當然想要一個單獨的汽車和摩托車桌子(也可能是車輛基地屬性的桌子)。 最好的方法是什么?
在MyDbContext類中擁有類型為DBSet的Vehicle
屬性。
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);
請記住,您的實體類中應該有一個Key Property( ID
或{ClassName}ID
)。 否則它會給你一個運行時錯誤! (是的,代碼將編譯。)
public abstract class Vehicle
{
public int ID { set; get; }
public double TopSpeed { get; set; }
}
編輯:根據評論
默認情況下,實體框架將執行每個層次結構的表 。 層次結構中的所有數據都保存在單個表中,並使用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);
}
輸出是
現在您應該能夠像這樣查詢您的車輛參賽作品
var vehicles = dbContext.Set<Vehicle>().Where(x => x.TopSpeed > 150).ToList();
結果就在這里
請注意,結果包含MotorCycle
類型和Car
類型。
檢查此鏈接以確定要使用的繼承策略。
您是否嘗試過僅使用DBSet為Vehicle提供自己的上下文? 我想那可能會為你做。
在繼承的類上使用DataAnnotation.Schema.Table(“TableName”)條目,觸發為繼承類型(table-per-type)創建新表,並消除父類型表中的Discriminator字段,而不是需要Fluent API代碼。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.