Как создать составной ключ, который является комбинацией базового класса и производного класса в Entity Framework Core - PullRequest
0 голосов
/ 06 января 2019

У меня есть требование создать составной ключ в Entity Framework.

Мой ключ базового класса - «Guid», и в классе ученика есть что-то уникальное, например «ID», которое можно прочитать. как "STUD01", который действительно требует читаемых уникальных данных.

[NotMapped]
public class BaseEntity
{
     public Guid Key { get; set; }
     public DateTime? DateCreated { get; set; }
     public string UserCreated { get; set; }
     public DateTime? DateModified { get; set; }
     public string UserModified { get; set; }
}

Вот мой Student класс

 public class Student : BaseEntity
 {
      public string Id { get; set; }
      public string Name { get; set; }
 }

Вот мой контекстный класс

public class SchoolContext: DbContext
{       
    public LibraContext(DbContextOptions<SchoolContext> options)
        : base(options)
    { }

    public DbSet<Student> Students { get; set; }
}

 protected override void OnModelCreating(ModelBuilder modelBuilder)
 {
     modelBuilder.Entity<BaseEntity>().Property(x => x.DateCreated).HasDefaultValueSql("GETDATE()");
     modelBuilder.Entity<BaseEntity>().Property(x => x.DateModified).HasDefaultValueSql("GETDATE()");

     //here is my composite key
     modelBuilder.Entity<Student>().HasKey(c => new { c.Key, c.Id });
 }

Я выполнил приведенные ниже команды миграции для создания сценария и обновления базы данных

Add-Migration -Name "InitialMigration" -Context "SchoolContext"

и я получаю эту ошибку:

Ключ не может быть настроен для ученика, потому что это производный тип. Ключ должен быть настроен для корневого типа «BaseClass». Если вы не собирались включать в модель «BaseClass», убедитесь, что он не включен в свойство DbSet вашего контекста, не указан в вызове конфигурации для ModelBuilder или не указан в свойстве навигации для включенного типа. в модели.

Как этого добиться?

Я использую ASP.NET Core 2.1

1 Ответ

0 голосов
/ 06 января 2019

Проблема заключается в том, что аннотация данных [Not Mapped] не игнорирует создание таблицы, поскольку Fluent API всегда имеет более высокий приоритет, чем аннотации данных (атрибуты). Таким образом, вы можете позвонить modelBuilder.Ignore<BaseEntity>(); после конфигурации BaseEntity в OnModelCreating, но вызов modelBuilder.Ignore<BaseEntity>(); потеряет настройки BaseEntity.

Так что лучшим решением будет:

Запишите конфигурацию для BaseEntity следующим образом:

public class BaseEntityConfigurations<TEntity> : IEntityTypeConfiguration<TEntity> where TEntity : BaseEntity
{
    public virtual void Configure(EntityTypeBuilder<TEntity> builder)
    {
        builder.Property(x => x.Key).HasDefaultValueSql("NEWID()");
        //CreatedDate 
        builder.Property(x => x.DateCreated).HasDefaultValueSql("GETDATE()");
        //Updated Date
        builder.Property(x => x.DateModified).HasDefaultValueSql("GETDATE()");
    }
}

Затем запишите конфигурацию для Student следующим образом:

public class StudentConfigurations : BaseEntityConfigurations<Student>
{
    public override void Configure(EntityTypeBuilder<Student> builder)
    {
        base.Configure(builder); // Must call this

       // composite key
        builder.HasKey(c => new { c.Key, c.Id });
    }
}

Затем в OnModelCreating следующим образом:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
     base.OnModelCreating(modelBuilder);

     modelBuilder.ApplyConfiguration(new StudentConfigurations());
}

Теперь все должно работать нормально!

Примечание. Если у вас уже есть база данных, она не будет работать при миграции. Вы должны сгенерировать новую таблицу с начальной миграцией, потому что ядро ​​Entity Framework не может изменить первичный ключ при миграции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...