kunci komposit sebagai kunci asing


91

Saya menggunakan kerangka Entitas 4.1 dalam aplikasi MVC 3. Saya memiliki entitas di mana saya memiliki kunci utama terdiri dari dua kolom (kunci komposit). Dan ini digunakan di entitas lain sebagai kunci asing. Bagaimana cara menciptakan hubungan? Dalam scnerios normal kami menggunakan:

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; }
} 

tetapi bagaimana jika kategori memiliki kunci dua kolom?

Jawaban:


169

Anda dapat menggunakan salah satu API yang lancar:

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});

    }
}

Atau anotasi data:

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; }
}

Apakah saya perlu menyimpan properti virtual (Kategori Kategori publik virtual {get; set;}) serta anovasi data?
DotnetSparrow

4
virtualpada properti navigasi diperlukan untuk pemuatan lambat. virtualpada properti skalar membantu pelacakan perubahan objek yang dilampirkan.
Ladislav Mrnka

4
Apa yang akan Anda lakukan jika nama kolom tabel kunci asing berbeda dari yang ada di induk? Misalnya, Dalam produk, bagaimana Anda akan memberi label pada atribut ForeignKey jika nama kolom terlihat seperti: PCategoryId2, PCategoryId3?

Mengenai baris ini: .HasRequired(p => p.Category)tetapi Producttidak memiliki properti Entitas Catagory tetapi dua id yang membuat kunci komposit dari sebuah kategori. Bisakah Anda jelaskan, karena saya yakin itu bahkan tidak akan bisa dikompilasi ... Terima kasih!
gdoron mendukung Monica

@gdoron: Productada Categorydi jawaban saya.
Ladislav Mrnka

26

Saya yakin cara termudah adalah menggunakan Anotasi Data pada properti Navigasi seperti ini: [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; }
}

Ini bekerja dengan baik. Saya juga lebih suka menggunakan ini pada Navigationproperti. Namun, bagaimana cara menyetel cascadeDelete: falseuntuk properti ini saja, bukan untuk seluruh situs? Terima kasih
RoLYroLLs

Dalam beberapa kasus, kunci asing juga merupakan bagian dari kunci komposit tabel saat ini. Cara ini berhasil. Sebaliknya (@Ladislov) tidak. Saya mendapat kesalahan: "Atribut Kolom Duplikat"
D. Kermott

RoLYroLLs: cascadeDelete disetel dalam file migrasi (setelah menggunakan perintah pengelola paket tambahkan migrasi). Contoh: AddForeignKey ("dbo.Product", "GuidedActivityID", "dbo.GuidedActivity", "ID", cascadeDelete: false);
Christophe
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.