Складання складових ключів спочатку за допомогою коду EF


115

Таблиця сервера Sql:

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

Як слід спочатку відобразити це в коді EF 6?

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

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

Я бачив кілька прикладів, коли вам потрібно встановити порядок для кожного стовпця, це потрібно?

Чи є десь офіційна документація на це?


Є чи або ? SomeIdstringint
Корі Адлер

@ IronMan84 Це рядок, я це виправлю.
лояльний потік

Відповіді:


187

Ви, безумовно, повинні розміщувати порядок стовпців, інакше як SQL Server повинен знати, хто з них першим? Ось що вам потрібно зробити у своєму коді:

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

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

Ви також можете подивитися на це питання ТАК . Якщо ви хочете отримати офіційну документацію, я рекомендую переглянути офіційний веб-сайт EF . Сподіваюся, це допомагає.

EDIT: Я щойно знайшов допис у блозі від Джулі Лерман із посиланнями на всі види доброти EF 6. Ви можете знайти все , що вам потрібно тут .


Як це зробити за допомогою EntityConfiguration? Насправді у мене немає сутності для таблиці приєднання ... У мене просто два об'єкти та EntityConfiguration на одному з них за допомогою .Map () для налаштування відображення.
Мир

31
otherwise how is SQL Server supposed to know which one goes first?- чому б не так, як він знає порядок для кожної іншої колонки?
Давор

1
EF не знає порядок інших стовпців, ви можете вставляти їх із стовпцями в будь-якому порядку, поки вказані імена. Якщо EF вимагає порядку для складеного ПК, він повинен бути пов'язаний з індексуванням.
Сільвен Gantois

@Davor Я думаю, що творці EF могли використати відображення для того, щоб зробити висновок про замовлення ключів / стовпців, але, можливо, існують міркування щодо ефективності цього. Я будь-який день прийматиму специфіку дизайну щодо більш повільної продуктивності, особливо в моєму DAL.
Якоб Стамм

47

Для картування складеного первинного ключа за допомогою Entity Framework ми можемо використовувати два підходи.

1) Перезаписавши метод OnModelCreating ()

Наприклад: у мене є клас моделей під назвою VehicleFeature, як показано нижче.

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

Код у моєму DBContext був би таким,

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) За анотаціями даних.

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

Перегляньте посилання нижче для отримання додаткової інформації.

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

2) Як додати складений унікальний ключ за допомогою EF 6 Fluent Api?


5
FYI для EF Core, варіант №2 неможливий , "Композиційні клавіші можна налаштувати лише за допомогою API Fluent - конвенції ніколи не встановлюють складений ключ, і ви не можете використовувати Анотації даних для його налаштування".
Tobias J

7

За допомогою конфігурації ви можете це зробити:

Model1
{
    int fk_one,
    int fk_two
}

Model2
{
    int pk_one,
    int pk_two,
}

то в контексті config

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

Де в контексті конфігурації?
Чарлі

Якщо ви налаштовуєте контекст за допомогою коду, використовуючи Fluent API ... розділ 7 . публічний клас MyContext: DbContext {захищений переосмислений недійсний OnModelCreating (модель DbModelBuilderBuilder) {modelBuilder.Entity <Model1> () .HasRequired (e => e.Model2). {e.fk_one, e.fk_two}) .WillCascadeOnDelete (помилково); }}
philn5d

Я виявив, що мені потрібно використовувати ModelBuilder замість DbModelBuilder на ядрі dotnet.
kiml42

6

Я думав, що я додам до цього питання, оскільки це найкращий результат пошуку в Google.

Як було відмічено в коментарях, в EF Core немає підтримки використання анотацій (атрибут Key), і це потрібно робити вільно.

Оскільки я працював над великою міграцією з EF6 на EF Core, це було не загрозою, і тому я спробував зламати його, використовуючи Reflection, щоб шукати атрибут Key, а потім застосовувати його під час 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);
}

Я не до кінця перевіряв це в усіх ситуаціях, але це працює в моїх основних тестах. Сподіваюся, що це комусь допоможе

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.