В EF Core 3 есть генератор ценности

в modelBUilder для объекта я пытаюсь установить даты создания и изменения при добавлении и обновлении с помощью специального генератора. Причина выбора этого пути заключается в том, что DbContext, который создает модели, используется в качестве базового класса. Этот базовый класс наследуется расширениями SQL Server и SQLite EFCore. Из-за этого в контексте должна быть явная функциональность базы данных. GetDateUTC() и триггеры, изначально реализованные в SQL Server.

modelBuilder.Entity<CommunicationSendRequest>(entity =>
            {
               ...

                entity.Property(p => p.CreatedAt).ValueGeneratedOnAdd().HasValueGenerator<CreatedAtTimeGenerator>();
                entity.Property(p => p.ModifiedAt).ValueGeneratedOnUpdate().HasValueGenerator<ModifiedAtTimeGenerator>();

            });

но то, что происходит при добавлении и обновлении, для обоих свойств всегда устанавливаются новые значения. Это означает, что для новых вставок устанавливается дата модификации, а для обновлений устанавливается дата создания. Который удаляет истину, созданную на дату.

Даты создания и изменения в

Вопрос в том, правильно ли настроены генераторы значений? Есть ли способ сделать это с помощью генераторов? В генераторах я пытался также проверить состояние и вернуть значение, только если состояние было добавлено или изменено. Но состояние всегда равнялось Отстраненному.

 public class CreatedAtTimeGenerator : ValueGenerator<DateTimeOffset>
    {
        public override DateTimeOffset Next(EntityEntry entry)
        {
            if (entry == null)
            {
                throw new ArgumentNullException(nameof(entry));
            }

            return DateTimeOffset.UtcNow;
        }

        public override bool GeneratesTemporaryValues { get; }
    }
    public class ModifiedAtTimeGenerator : ValueGenerator<DateTimeOffset>
    {
        public override DateTimeOffset Next(EntityEntry entry)
        {
            if (entry == null)
            {
                throw new ArgumentNullException(nameof(entry));
            }

            return DateTimeOffset.UtcNow;
        }

        public override bool GeneratesTemporaryValues { get; }
    }

person ChampChris    schedule 29.03.2020    source источник
comment
Вы пытались добавить ValueGeneratedOnAdd() после объявления генератора? (Выстрел в темноте, здесь)   -  person Guillermo Prandi    schedule 05.08.2020
comment
@GuillermoPrandi я отказался от этого подхода и установил даты создания и изменения в переопределении savechanges()   -  person ChampChris    schedule 06.08.2020
comment
HasValueGenerator - это просто генератор значений на стороне модели, который заполняет значение для свойства вашей модели, когда оно имеет значение по умолчанию (null для объекта, 0 для целого числа,...) И значение свойства заполняется, когда объект добавляется в DbContext . Таким образом, в вашем случае вы всегда оставляете все свойства даты по умолчанию, каждый раз, когда они добавляются в DbContext, они будут заполняться вашим генератором (ВСЕГДА). ValueGeneratedOnXXX работает на более позднем этапе (перед сохранением объекта), поэтому все значения свойств, отличные от значений по умолчанию, будут сохранены и сохранены. Это может иметь смысл только тогда, когда нет генератора значений.   -  person Hopeless    schedule 21.11.2020
comment
включая создание ценности, я думаю, что EFCore был разработан запутанным образом. В этом случае ValueGeneratedOnAdd кажется недействительным и бесполезным. Если вы хотите, чтобы какое-то значение генерировалось при добавлении, как в этом случае, вы не должны использовать генератор значений, возможно, вместо этого подготовьте какое-то значение по умолчанию sql.   -  person Hopeless    schedule 21.11.2020


Ответы (1)


Что я на самом деле сделал, так это полностью ушел от концепции ValueGenerate и обработал ее созданием CreatedAt, ModifiedAt и добавил после того, как этот пост был создан даты DeletedAt, переопределив методы SaveChanges().

 public override int SaveChanges()
    {
        var selectedEntityList = ChangeTracker.Entries()
            .Where(x => (x.Entity is IEntityCreatedAt ||
                         x.Entity is IEntityModifiedAt ||
                         x.Entity is IEntityIsDeleted) &&
                        (x.State == EntityState.Added || x.State == EntityState.Modified)).ToList();

        selectedEntityList.ForEach(entity =>
        {
            if (entity.State == EntityState.Added)
            {
                if (entity.Entity is IEntityCreatedAt)
                    ((IEntityCreatedAt)entity.Entity).CreatedAt = DateTimeOffset.UtcNow;
            }

            if (entity.State == EntityState.Modified)
            {
                if (entity.Entity is IEntityModifiedAt)
                    ((IEntityModifiedAt)entity.Entity).ModifiedAt = DateTimeOffset.UtcNow;

                if (entity.Entity is IEntityIsDeleted)
                    if (((IEntityIsDeleted)entity.Entity).IsDeleted)
                        ((IEntityIsDeleted)entity.Entity).DeletedAt = DateTimeOffset.UtcNow;
            }
        });

        return base.SaveChanges();
    }
person ChampChris    schedule 29.11.2020