簡體   English   中英

在EF4 Code-First中按基類型查詢

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM