Trước tiên, ánh xạ các khóa tổng hợp bằng mã EF


115

Bảng máy chủ Sql:

SomeId PK varchar(50) not null 
OtherId PK int not null

Trước tiên, tôi nên lập bản đồ này như thế nào trong mã EF 6?

public class MyTable
{
    [Key]
    public string SomeId { get; set; }

    [Key]
    public int OtherId { get; set; }
}

Tôi đã thấy một số ví dụ mà bạn phải đặt thứ tự cho mỗi cột, điều đó có bắt buộc không?

Có tài liệu chính thức về điều này ở đâu đó không?


SomeIdmột stringhay một int?
Corey Adler

@ IronMan84 Đó là một chuỗi, tôi sẽ sửa điều đó.
loyalflow

Câu trả lời:


186

Bạn chắc chắn cần phải đặt theo thứ tự cột, nếu không thì làm thế nào SQL Server phải biết cái nào đi trước? Đây là những gì bạn cần làm trong mã của mình:

public class MyTable
{
  [Key, Column(Order = 0)]
  public string SomeId { get; set; }

  [Key, Column(Order = 1)]
  public int OtherId { get; set; }
}

Bạn cũng có thể xem câu hỏi SO này . Nếu bạn muốn có tài liệu chính thức, tôi khuyên bạn nên xem trang web chính thức của EF . Hi vọng điêu nay co ich.

CHỈNH SỬA: Tôi vừa tìm thấy một bài đăng trên blog của Julie Lerman với các liên kết đến tất cả các loại EF 6 tốt. Bạn có thể tìm thấy bất cứ thứ gì bạn cần ở đây .


Làm cách nào để bạn thực hiện việc này thông qua EntityConfiguration? Tôi thực sự không có một thực thể cho bảng nối ... Tôi chỉ có hai thực thể và một EntityConfiguration trên một trong số chúng với .Map () để thiết lập ánh xạ.
Mir

31
otherwise how is SQL Server supposed to know which one goes first?- tại sao không giống như cách nó biết thứ tự cho mọi cột khác?
Davor

1
EF không biết thứ tự của các cột khác, bạn có thể chèn các cột theo bất kỳ thứ tự nào miễn là tên được chỉ định. Nếu EF yêu cầu thứ tự cho PK tổng hợp thì nó phải liên quan đến việc lập chỉ mục.
Sylvain Gantois

@Davor Tôi tưởng tượng những người tạo EF có thể đã sử dụng phản xạ để suy ra thứ tự khóa / cột, nhưng có lẽ có những cân nhắc về hiệu suất khi không thực hiện điều này. Tôi sẽ xem xét cụ thể về thời gian thiết kế so với hiệu suất chậm hơn bất kỳ ngày nào, đặc biệt là trong DAL của tôi.
Jacob Stamm

47

Để ánh xạ khóa chính hỗn hợp sử dụng khung thực thể, chúng ta có thể sử dụng hai cách tiếp cận.

1) Bằng cách ghi đè phương thức OnModelCreating ()

Ví dụ: Tôi có lớp mô hình tên là VehicleFeature như hình dưới đây.

public class VehicleFeature
{
    public int VehicleId { get; set; }
    public int FeatureId{get;set;}
    public Vehicle Vehicle{get;set;}
    public Feature Feature{get;set;}
}

Mã trong DBContext của tôi sẽ giống như,

public class VegaDbContext : DbContext
{
    public DbSet<Make> Makes{get;set;}

    public DbSet<Feature> Features{get;set;}
    public VegaDbContext(DbContextOptions<VegaDbContext> options):base(options)        
    {           

    }
    // we override the OnModelCreating method here.
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<VehicleFeature>().HasKey(vf=> new {vf.VehicleId, vf.FeatureId});
    }
}

2) Bằng Chú thích Dữ liệu.

public class VehicleFeature
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]  
    [Key]
    public int VehicleId { get; set; }
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]   
    [Key]
    public int FeatureId{get;set;}
    public Vehicle Vehicle{get;set;}
    public Feature Feature{get;set;}
}

Vui lòng tham khảo các liên kết dưới đây để biết thêm thông tin.

1) https://msdn.microsoft.com/en-us/library/jj591617(v=vs.113).aspx

2) Làm cách nào để thêm khóa duy nhất tổng hợp bằng EF 6 Fluent Api?


5
FYI cho EF Core, Lựa chọn # 2 là không thể , "chìa khóa composite chỉ có thể được cấu hình bằng cách sử dụng API thạo - ước sẽ không bao giờ thiết lập một phím composite và bạn không thể sử dụng dữ liệu Chú thích để cấu hình một."
Tobias J

7

Thông qua Cấu hình, bạn có thể làm điều này:

Model1
{
    int fk_one,
    int fk_two
}

Model2
{
    int pk_one,
    int pk_two,
}

sau đó trong cấu hình ngữ cảnh

public class MyContext : DbContext
{
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Model1>()
            .HasRequired(e => e.Model2)
            .WithMany(e => e.Model1s)
            .HasForeignKey(e => new { e.fk_one, e.fk_two })
            .WillCascadeOnDelete(false);
    }
}

Ở đâu trong cấu hình ngữ cảnh?
Charlie

Nếu bạn đang định cấu hình ngữ cảnh thông qua mã bằng API Fluent ... phần 7 . public class MyContext: DbContext {được bảo vệ ghi đè void OnModelCreating (DbModelBuilder modelBuilder) {modelBuilder.Entity <Model1> () .HasRequired (e => e.Model2) .WithMany (e => e.Model1s) .HasForeignKey (e => new {e.fk_one, e.fk_two}) .WillCascadeOnDelete (sai); }}
philn5d

Tôi thấy mình phải sử dụng ModelBuilder thay vì DbModelBuilder trên lõi dotnet.
kiml42,

6

Tôi nghĩ tôi sẽ thêm vào câu hỏi này vì nó là kết quả tìm kiếm hàng đầu của google.

Như đã được lưu ý trong các nhận xét, trong EF Core không hỗ trợ việc sử dụng chú thích (Thuộc tính khóa) và nó phải được thực hiện một cách thông thạo.

Vì tôi đang làm việc trên một quá trình di chuyển lớn từ EF6 sang EF Core, điều này không đáng có và vì vậy tôi đã cố gắng hack nó bằng cách sử dụng Reflection để tìm thuộc tính Khóa và sau đó áp dụng nó trong OnModelCreating

// get all composite keys (entity decorated by more than 1 [Key] attribute
foreach (var entity in modelBuilder.Model.GetEntityTypes()
    .Where(t => 
        t.ClrType.GetProperties()
            .Count(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(KeyAttribute))) > 1))
{
    // get the keys in the appropriate order
    var orderedKeys = entity.ClrType
        .GetProperties()
        .Where(p => p.CustomAttributes.Any(a => a.AttributeType == typeof(KeyAttribute)))
        .OrderBy(p => 
            p.CustomAttributes.Single(x => x.AttributeType == typeof(ColumnAttribute))?
                .NamedArguments?.Single(y => y.MemberName == nameof(ColumnAttribute.Order))
                .TypedValue.Value ?? 0)
        .Select(x => x.Name)
        .ToArray();

    // apply the keys to the model builder
    modelBuilder.Entity(entity.ClrType).HasKey(orderedKeys);
}

Tôi chưa kiểm tra đầy đủ điều này trong mọi tình huống, nhưng nó hoạt động trong các bài kiểm tra cơ bản của tôi. Hy vọng điều này sẽ giúp ai đó

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.