Önce EF kodunu kullanarak bileşik anahtarları eşleme


115

Sql sunucu tablosu:

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

Bunu önce EF 6 kodunda nasıl eşleştirmeliyim?

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

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

Her sütun için sırayı ayarlamanız gereken bazı örnekler gördüm, bu gerekli mi?

Bununla ilgili bir yerde resmi belgeler var mı?


SomeIdbir stringveya int?
Corey Adler

@ IronMan84 Bu bir dizedir, bunu düzelteceğim.
loyalflow

Yanıtlar:


187

Kesinlikle sütun sırasını koymanız gerekiyor, aksi halde SQL Server hangisinin önce gittiğini nasıl bilebilir? Kodunuzda yapmanız gerekenler:

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

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

Bu SO sorusuna da bakabilirsiniz . Resmi belgeler istiyorsanız, resmi EF web sitesine bakmanızı tavsiye ederim . Bu yardımcı olur umarım.

DÜZENLEME: Julie Lerman'dan her türden EF 6 iyiliğine bağlantılar içeren bir blog yazısı buldum. İhtiyacınız olan her şeyi burada bulabilirsiniz .


Bunu bir EntityConfiguration aracılığıyla nasıl yaparsınız? Aslında birleştirme tablosu için bir varlığım yok ... Eşlemeyi ayarlamak için bunlardan birinde .Map () ile iki varlık ve bir EntityConfiguration var.
Mir

31
otherwise how is SQL Server supposed to know which one goes first?- neden diğer sütunların sırasını aynı şekilde bilmiyor?
Davor

1
EF diğer sütunların sırasını bilmez, adlar belirtildiği sürece herhangi bir sırada sütunlarla ekleyebilirsiniz. EF, bileşik PK siparişini gerektiriyorsa, dizin oluşturmayla ilişkili olması gerekir.
Sylvain Gantois

@Davor EF yaratıcılarının anahtar / sütun sırasını çıkarmak için yansımayı kullanmış olabileceğini düşünüyorum, ancak bunu yapmamak için performans faktörleri olabilir. Tasarım zamanı özgüllüğünü her gün daha yavaş performans yerine, özellikle de DAL'ımda alacağım.
Jacob Stamm

47

Varlık çerçevesini kullanarak Bileşik birincil anahtarı Eşlemek için iki yaklaşım kullanabiliriz.

1) OnModelCreating () Yöntemini Geçersiz Kılarak

Örneğin, aşağıda gösterildiği gibi VehicleFeature adlı model sınıfım var.

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

DBContext'imdeki Kod şöyle olacaktır:

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) Veri Ek Açıklamaları ile.

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

Daha fazla bilgi için lütfen aşağıdaki bağlantılara bakın.

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

2) EF 6 Fluent Api kullanarak birleşik benzersiz anahtar nasıl eklenir?


5
FYI for EF Core, Seçenek # 2 mümkün değil , "Bileşik anahtarlar yalnızca Fluent API kullanılarak yapılandırılabilir - kurallar hiçbir zaman bileşik anahtar ayarlamaz ve birini yapılandırmak için Veri Ek Açıklamalarını kullanamazsınız."
Tobias J

7

Yapılandırma aracılığıyla şunları yapabilirsiniz:

Model1
{
    int fk_one,
    int fk_two
}

Model2
{
    int pk_one,
    int pk_two,
}

sonra bağlamda yapılandırma

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

Bağlam yapılandırmasında nerede?
Charlie

Fluent API kullanarak kod aracılığıyla bağlamı yapılandırıyorsanız ... bölüm 7 . public class MyContext: DbContext {korumalı geçersiz kılma void OnModelCreating (DbModelBuilder modelBuilder) {modelBuilder.Entity <Model1> () .HasRequired (e => e.Model2) .WithMany (e => e.Model1s) .HasForeignKey ( {e.fk_one, e.fk_two}) .WillCascadeOnDelete (yanlış); }}
philn5d

Dotnet çekirdeğinde DbModelBuilder yerine ModelBuilder kullanmak zorunda olduğumu fark ettim.
kiml42

6

En iyi google arama sonucu olduğu için bu soruya ekleyeceğimi düşündüm.

Yorumlarda belirtildiği gibi, EF Core'da ek açıklamaların (Anahtar özniteliği) kullanımı için destek yoktur ve akıcı bir şekilde yapılmalıdır.

EF6'dan EF Core'a büyük bir geçiş üzerinde çalıştığım için bu tatsızdı ve bu yüzden Anahtar özelliğini aramak için Reflection'ı kullanarak onu hacklemeye ve ardından OnModelCreating sırasında uygulamaya çalıştım

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

Bunu her durumda tam olarak test etmedim, ancak temel testlerimde işe yarıyor. Umarım bu birine yardımcı olur

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.