Исключение по индексным аннотациям данных из базового класса - PullRequest
0 голосов
/ 03 октября 2018

Я начинаю с ASP.net Core и создаю свои модели.
Я только что создал две: одну с именем dto, которая будет основой для всех моих моделей баз данных, и будет выглядеть так:

public abstract class Dto
{
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }
    [Clustered]
    public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
    public DateTime LastUpdate { set; get; } 
}

другой называется subscription, и это выглядит так:

public class Subscription:Dto
{
    public string Name { get; set; } 
    public decimal Price { set; get; }
    public string MeliApiKey { get; set; }
    public int MaxQueries { get; set; }
    public int UsedQueries { get; set; }

}

У меня есть следующая конфигурация на Fluent API:

modelBuilder.Entity<Dto.Dto>().Property(x => x.CreatedAt).HasDefaultValueSql("SYSUTCDATETIME()");
modelBuilder.Entity<Dto.Dto>().Property(x => x.LastUpdate).HasComputedColumnSql("SYSUTCDATETIME()");

foreach (var entity in modelBuilder.Model.GetEntityTypes())
{
    foreach (var prop in entity.GetProperties())
    {
        var attr = prop.PropertyInfo?.GetCustomAttribute<ClusteredAttribute>(true);
        if (attr != null)
        {
            var index = entity.AddIndex(prop);
            index.IsUnique = true;
            index.SqlServer().IsClustered = true;
        }
    }
}

Я добавил только subscription как dbset, потому что я не хочу наследования таблиц в иерархии с dto.

Когда я запускаю add-migration, яполучить следующую ошибку:

"Индекс {'CreatedAt'} не может быть добавлен к типу сущности 'Подписка', так как индекс для тех же свойств уже существует для типа сущности 'Dto'"

Теперь я погуглил ошибку, но нигде не вижу, как ее решить.

Должен ли я удалить класс dto и добавить те же свойствакаждому объекту, который будет представлять мою модель?

Ответы [ 2 ]

0 голосов
/ 03 октября 2018

Я закончил тем, что удалил эти строки:

modelBuilder.Entity<Dto.Dto>().Property(x => x.CreatedAt).HasDefaultValueSql("SYSUTCDATETIME()");
modelBuilder.Entity<Dto.Dto>().Property(x => x.LastUpdate).HasComputedColumnSql("SYSUTCDATETIME()");

Поскольку они по какой-то причине включили класс Dto в иерархию Entity Framework, создав наследование таблиц на иерархию (что привело к созданию только одной базы данных таблиц).

затем я переписал код OnModelCreating следующим образом:

foreach (var entity in modelBuilder.Model.GetEntityTypes())
        {
            if (entity.ClrType.IsSubclassOf(typeof(Dto.Dto)))
            {

                modelBuilder.Entity(entity.ClrType)
                    .HasKey(nameof(Dto.Dto.Id)).ForSqlServerIsClustered(false);

                modelBuilder.Entity(entity.ClrType)
                    .Property(nameof(Dto.Dto.CreatedAt))
                    .HasDefaultValueSql("SYSUTCDATETIME()");

                modelBuilder.Entity(entity.ClrType)
                    .Property(nameof(Dto.Dto.LastUpdate))
                    .HasComputedColumnSql("SYSUTCDATETIME()");

                foreach (var prop in entity.GetProperties())
                {

                    var attr = prop.PropertyInfo?.GetCustomAttribute<ClusteredAttribute>(true);
                    if (attr != null)
                    {
                        var index = entity.AddIndex(prop);
                        index.IsUnique = true;
                        index.SqlServer().IsClustered = true;

                    }

                }
            }
        }

это если if (entity.ClrType.IsSubclassOf(typeof(Dto.Dto))) - быстро отбросить таблицы, созданные ASP.net Core, поэтому изменения вносятся только длямои объекты, которые наследуются от Dto.

Этот код:

modelBuilder.Entity(entity.ClrType)
                .Property(nameof(Dto.Dto.CreatedAt))
                .HasDefaultValueSql("SYSUTCDATETIME()");

modelBuilder.Entity(entity.ClrType)
                .Property(nameof(Dto.Dto.LastUpdate))
                .HasComputedColumnSql("SYSUTCDATETIME()");

сообщает платформе сущности, чтобы создать столбец CreateAt с текущим временем UTC имеет значение по умолчанию и обновить столбец LastUpdate с текущимВремя UTC для фактической сущности в цикле for.

и, наконец, этот код получил ошибку, потому что класс Dto был включен в объекты базы данных, поэтому он создает для него индекс и с тех пор включает этот классв объектах базы данных запускает TPH, когда следующий объект тоже пытается создать индекс, появляется ошибка (мыпытаясь создать тот же индекс в той же таблице, потому что с TPH у нас есть только одна таблица).

foreach (var prop in entity.GetProperties())
        {

            var attr = prop.PropertyInfo?.GetCustomAttribute<ClusteredAttribute>(true);
            if (attr != null)
            {
                var index = entity.AddIndex(prop);
                index.IsUnique = true;
                index.SqlServer().IsClustered = true;
            }
        }

но теперь, когда мы разделили таблицы для каждой сущности, она просто работает.

ответ Мохо очень помог.

вот другие ответы, которые помогли мне достичь этого:

Как проверить, является ли тип подтипом ИЛИ типомобъекта?

EF Core Добавить миграцию Отладка

0 голосов
/ 03 октября 2018

Как указывается в ошибке, а индекс уже определен в свойстве для базового класса.Убедитесь, что свойство объявлено в том же типе объекта, который вы сейчас обрабатываете, что-то вроде:

var propertiesToProcess = entity.GetProperties()
    .Where( p => entity.ClrType == p.PropertyInfo.DeclaringType );
...