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 のテーブルが 1 つの Vehicle テーブルに結合されました。私は間違いなく、車とバイク用に別のテーブルが必要です (そして、おそらく車両ベースのプロパティ用のテーブルも必要です)。これを行う最善の方法は何ですか?

4

3 に答える 3

11

MyDbContext クラスにタイプ DBSet の Vehicles Properties があり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);

IDエンティティ クラス (または)にキー プロパティが必要であることに注意してください{ClassName}ID。そうしないと、実行時エラーが発生します。(はい、コードはコンパイルされます。)

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

編集:コメントによると

デフォルトでは、Entity Framework はTable Per Hierarchyを実行します。階層内のすべてのデータは単一のテーブルに保存され、Discriminator列を使用してどのレコードがどのサブタイプに属しているかを識別します。その結果、階層内のすべてのクラスのプロパティと同じ列を持つ 1 つの Vehicle テーブルがあり、" Discriminator" という追加の列があります。車のレコードの場合、Discriminator 列内に「車」の値が含まれます。

ここに画像の説明を入力

タイプごとに単一のテーブルを作成する場合は、Table Per Typeを使用します。Entity Framework は、基本クラスのテーブルと、すべての子クラスの個別のテーブルを作成します。

これを実現するには、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結果にはtype とtypeの両方が含まれていることに注意してくださいCar

このリンクをチェックして、使用する継承戦略を決定してください。

于 2012-05-02T19:24:25.630 に答える
0

DBSet だけで Vehicle に独自のコンテキストを与えてみましたか? 私はそれがあなたのためにそれをするかもしれないと思います.

于 2012-05-02T19:44:05.547 に答える
0

継承されたクラスで DataAnnotation.Schema.Table("TableName") エントリを使用すると、継承された型 (table-per-type) の新しいテーブルの作成がトリガーされ、親型テーブルの Discriminator フィールドが削除されます。 Fluent API コードが必要です。

于 2012-07-24T14:27:41.670 に答える