Сопоставление составных ключей сначала с использованием кода EF

Таблица 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; }
}

Я видел несколько примеров, где вы должны установить порядок для каждого столбца, это обязательно?

Есть ли где-нибудь официальная документация по этому поводу?


person loyalflow    schedule 05.11.2013    source источник
comment
@IronMan84 IronMan84 Это строка, я это исправлю.   -  person loyalflow    schedule 05.11.2013


Ответы (4)


Вам определенно нужно указать порядок столбцов, иначе как SQL Server должен знать, какой из них идет первым? Вот что вам нужно сделать в вашем коде:

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

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

Вы также можете просмотреть этот вопрос SO. Если вам нужна официальная документация, я бы рекомендовал посетить официальный веб-сайт EF. Надеюсь это поможет.

РЕДАКТИРОВАТЬ: я только что нашел сообщение в блоге от Джули Лерман со ссылками на все виды EF 6. Вы можете найти все, что вам нужно здесь< /а>.

person Corey Adler    schedule 05.11.2013
comment
Как вы делаете это через EntityConfiguration? На самом деле у меня нет объекта для таблицы соединений... У меня есть только два объекта и EntityConfiguration на одном из них с .Map() для настройки сопоставления. - person Mir; 06.05.2014
comment
otherwise how is SQL Server supposed to know which one goes first? - почему не так же, как он знает порядок для каждого другого столбца? - person Davor; 18.02.2015
comment
EF не знает порядок других столбцов, вы можете вставлять столбцы в любом порядке, если указаны имена. Если EF требует порядка составного ПК, он должен быть связан с индексацией. - person Sylvain Gantois; 23.03.2019
comment
@Davor Я полагаю, что создатели EF могли бы использовать отражение для определения порядка ключей / столбцов, но, возможно, есть соображения производительности, чтобы не делать этого. В любой день я предпочту особенности времени разработки более медленной производительности, особенно в моем DAL. - person Jacob Stamm; 04.04.2019
comment
Думаю, имеет смысл требовать заказ заранее. Если вы однажды переупорядочите эти свойства, вы будете очень злы, узнав, что инфраструктура сущностей перестала работать. - person fjch1997; 18.12.2020
comment
@Davor, порядок используется TEntity Find(params object[] keyValues), чтобы узнать порядок значений в keyValues. - person MarkMYoung; 04.05.2021

Для сопоставления первичного ключа Composite с использованием 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?

person Krishna    schedule 03.09.2017
comment
К сведению для EF Core, вариант № 2 невозможен Составные ключи можно настроить только с помощью Fluent API — соглашения никогда не будут устанавливать составной ключ, и вы не можете использовать аннотации к данным для его настройки. - person Tobias J; 01.11.2018

Я подумал, что добавлю к этому вопросу, так как это лучший результат поиска Google.

Как было отмечено в комментариях, в EF Core нет поддержки использования аннотаций (атрибута Key), и это необходимо делать с помощью Fluent.

Поскольку я работал над большой миграцией с 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);
}

Я не проверял это полностью во всех ситуациях, но в моих базовых тестах это работает. Надеюсь, это поможет кому-то

person cmorgan091    schedule 14.05.2019

Через Конфигурацию вы можете сделать это:

Model1
{
    int fk_one,
    int fk_two
}

Model2
{
    int pk_one,
    int pk_two,
}

то в конфиге контекста

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);
    }
}
person philn5d    schedule 18.07.2014
comment
Где в контексте конфиг? - person Charlie; 21.11.2016
comment
Если вы настраиваете контекст с помощью кода с помощью Fluent API... раздел 7. открытый класс 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); } } - person philn5d; 07.02.2017
comment
Я обнаружил, что мне пришлось использовать ModelBuilder вместо DbModelBuilder в ядре dotnet. - person kiml42; 22.08.2018