khóa tổng hợp làm khóa ngoại


91

Tôi đang sử dụng Entity framework 4.1 trong ứng dụng MVC 3. Tôi có một thực thể mà tôi có khóa chính bao gồm hai cột (khóa tổng hợp). Và điều này đang được sử dụng trong một thực thể khác làm khóa ngoại. Làm thế nào để tạo mối quan hệ? Trong các ống kính thông thường, chúng tôi sử dụng:

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

nhưng nếu danh mục có khóa hai cột thì sao?

Câu trả lời:


169

Bạn có thể sử dụng API thông thạo:

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

    }
}

Hoặc chú thích dữ liệu:

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

Tôi có cần giữ lại các thuộc tính ảo (public virtual Category Category {get; set;}) cũng như thông báo dữ liệu không?
DotnetSparrow

4
virtualtrên thuộc tính điều hướng là cần thiết cho tải chậm. virtualtrên thuộc tính vô hướng giúp theo dõi thay đổi của các đối tượng đính kèm.
Ladislav Mrnka

4
Bạn sẽ làm gì nếu tên cột của bảng khóa ngoại khác với tên cột trong bảng chính? Ví dụ trước, Trong sản phẩm, bạn sẽ gắn nhãn thuộc tính ForeignKey như thế nào nếu tên cột trông giống như: PCategoryId2, PCategoryId3?

Liên quan đến dòng này: .HasRequired(p => p.Category)nhưng Productkhông có thuộc tính của Thực thể Catagory mà có hai id tạo nên khóa tổng hợp của một catagory. Bạn có thể vui lòng giải thích, bởi vì tôi tin rằng nó thậm chí sẽ không biên dịch ... Cảm ơn!
gdoron đang hỗ trợ Monica

@gdoron: ProductCategorytrong câu trả lời của tôi.
Ladislav Mrnka

25

Tôi tin rằng cách dễ nhất là sử dụng Chú thích dữ liệu trên thuộc tính Điều hướng như sau: [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; }
}

Điều này làm việc tuyệt vời. Tôi cũng thích sử dụng điều này trên Navigationcác tài sản. Tuy nhiên, làm cách nào để tôi có thể đặt chỉ cascadeDelete: falsecho thuộc tính này, không phải trên toàn bộ trang web? Cảm ơn
RoLYroLLs 21/03/18

Trong một số trường hợp, khóa ngoại cũng là một phần của khóa tổng hợp của bảng hiện tại. Cách này đã hiệu quả. Theo cách khác (@Ladislov) thì không. Tôi đã nhận lỗi: "thuộc tính Column Duplicate"
D. Kermott

RoLYroLLs: cascadeDelete được đặt trong tệp di chuyển (sau khi sử dụng lệnh trình quản lý gói bổ sung di chuyển). Ví dụ: AddForeignKey ("dbo.Product", "GuidedActivityID", "dbo.GuidedActivity", "ID", cascadeDelete: false);
Christophe
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.