外部キーとしての複合キー


91

MVC3アプリケーションでEntityFramework4.1を使用しています。主キーが2つの列(複合キー)で構成されているエンティティがあります。そして、これは別のエンティティで外部キーとして使用されています。関係を作成する方法は?通常のscneriosでは以下を使用します:

public class Category
{
    public string CategoryId { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Product> Products { get; set; }
}

public class Product
{
    public int ProductId { get; set; }
    public string Name { get; set; }
    public string CategoryId { get; set; }

    public virtual Category Category { get; set; }
} 

しかし、カテゴリに2つの列キーがある場合はどうなりますか?

回答:


169

次のいずれかの流暢なAPIを使用できます。

public class Category
{
    public int CategoryId1 { get; set; }
    public int CategoryId2 { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Product> Products { get; set; }
}

public class Product
{
    public int ProductId { get; set; }
    public string Name { get; set; }
    public int CategoryId1 { get; set; }
    public int CategoryId2 { get; set; }

    public virtual Category Category { get; set; }
}

public class Context : DbContext
{
    public DbSet<Category> Categories { get; set; }
    public DbSet<Product> Products { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<Category>()
            .HasKey(c => new {c.CategoryId1, c.CategoryId2});

        modelBuilder.Entity<Product>()
            .HasRequired(p => p.Category)
            .WithMany(c => c.Products)
            .HasForeignKey(p => new {p.CategoryId1, p.CategoryId2});

    }
}

またはデータ注釈:

public class Category
{
    [Key, Column(Order = 0)]
    public int CategoryId2 { get; set; }
    [Key, Column(Order = 1)]
    public int CategoryId3 { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Product> Products { get; set; }
}

public class Product
{
    [Key]
    public int ProductId { get; set; }
    public string Name { get; set; }
    [ForeignKey("Category"), Column(Order = 0)]
    public int CategoryId2 { get; set; }
    [ForeignKey("Category"), Column(Order = 1)]
    public int CategoryId3 { get; set; }

    public virtual Category Category { get; set; }
}

仮想プロパティ(パブリック仮想カテゴリカテゴリ{get; set;})とデータの革新を保持する必要がありますか?
DotnetSparrow 2011年

4
virtual遅延読み込みには、ナビゲーションプロパティが必要です。virtualスカラープロパティは、アタッチされたオブジェクトの変更追跡に役立ちます。
Ladislav Mrnka 2011年

4
外部キーテーブルの列名が親の列名と異なる場合はどうしますか?たとえば、製品では、列名がPCategoryId2、PCategoryId3のようになっている場合、ForeignKey属性にどのようにラベルを付けますか?

この行に関して:.HasRequired(p => p.Category)ただしProductエンティティの プロパティはありませんがCatagory、カテゴリの複合キーを作成する2つのIDがあります。コンパイルすらしないと思うので、説明してもらえますか…ありがとう!
–gdoronはモニカをサポートしています2012

@gdoron:Product持っているCategory私の答えに。
Ladislav Mrnka 2012

25

最も簡単な方法は、Navigationプロパティで次のようにデータ注釈を使用することだと思います。 [ForeignKey("CategoryId1, CategoryId2")]

public class Category
{
    [Key, Column(Order = 0)]
    public int CategoryId1 { get; set; }
    [Key, Column(Order = 1)]
    public int CategoryId2 { get; set; }
    public string Name { get; set; }

    public virtual ICollection<Product> Products { get; set; }
}

public class Product
{
    [Key]
    public int ProductId { get; set; }
    public string Name { get; set; }
    public int CategoryId1 { get; set; }
    public int CategoryId2 { get; set; }

    [ForeignKey("CategoryId1, CategoryId2")]
    public virtual Category Category { get; set; }
}

これはうまくいきました。私もこれをNavigationプロパティで使用することを好みます。ただし、cascadeDelete: falseサイト全体ではなく、このプロパティのみに設定するにはどうすればよいですか?ありがとう
RoLYroLLs 2018年

場合によっては、外部キーも現在のテーブルの複合キーの一部です。このように機能しました。他の方法(@Ladislov)はしませんでした。「重複する列属性」というエラーが発生しました
D. Kermott 2018年

RoLYroLLs:cascadeDeleteは移行ファイルに設定されます(add-migration package managerコマンドを使用した後)。例:AddForeignKey( "dbo.Product"、 "GuidedActivityID"、 "dbo.GuidedActivity"、 "ID"、cascadeDelete:false);
クリストフ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.