Подтвердить что ты не робот

Добавление CreateDate к объекту с использованием Entity Framework 5 Code First

Я пытаюсь добавить свойство CreatedDate для объектов в моей модели и использую сначала код EF5. Я хочу, чтобы эта дата не менялась после установки, я хочу, чтобы она была датой UTC. Я не хочу использовать конструктор, поскольку у меня есть много объектов в моей модели, которые я хочу наследовать от абстрактного класса, содержащего свойство CreatedDate, и я не могу принудительно использовать конструктор с интерфейсом.

Я пробовал разные аннотации данных, и я попытался написать инициализатор базы данных, который бы взял конкретный тип объекта и написал ограничение на изменение с getdate() значением по умолчанию для правильных table_name и column_name, но Я не смог правильно написать этот код.

Пожалуйста, не обращайтесь к AuditDbContext - Контекст аудита структуры Entity Framework или EntityFramework.Extended, поскольку они не делают то, что мне нужно здесь.

UPDATE

My CreatedDate имеет значение null на SaveChanges(), потому что я передаю ViewModel в мое представление, у которого в нем нет свойства аудита, называемого CreatedDate. И даже если я передал модель моему представлению, я не редактирую или не сохраняю CreatedDate в представлении.

Я прочитал здесь, что я мог бы добавить [DatabaseGenerated(DatabaseGeneratedOption.Identity)], и это будет означать, что EF правильно сохранит CreatedDate после Вставки и обновления, но не позволит ему меняет мое приложение: но я просто получаю ошибку Cannot insert explicit value for identity column in table when IDENTITY_INSERT is set to OFF, добавляя этот атрибут.

Я собираюсь переключиться на EF Model First, потому что это простое требование к базе данных смешно реализовать в Code First.

4b9b3361

Ответ 1

Вот как я это сделал:

[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreatedDate{ get; set; }

в моем методе Up() миграции:

AddColumn("Agents", "CreatedDate", n => n.DateTime(nullable: false, defaultValueSql: "GETUTCDATE()"));

Ответ 2

Переопределите метод SaveChanges в вашем контексте:

public override int SaveChanges()
{
  DateTime saveTime = DateTime.UtcNow;
  foreach (var entry in this.ChangeTracker.Entries().Where(e => e.State == (EntityState) System.Data.EntityState.Added))
   {
     if (entry.Property("CreatedDate").CurrentValue == null)
       entry.Property("CreatedDate").CurrentValue = saveTime;
    }
    return base.SaveChanges();

}

Обновлено из-за комментариев: только недавно добавленные объекты будут иметь свою дату.

Ответ 3

Итак, основная проблема здесь заключалась в том, что CreateDate обновлялся каждый раз, когда я вызывал SaveChanges, и поскольку я не передавал CreateDate в мои представления, он обновлялся до NULL или MinDate by Entity Framework.

Решение было простым, зная, что мне нужно только установить CreateDate, когда EntityState.Added, я просто установил свой entity.CreatedDate.IsModified = false, прежде чем выполнять какую-либо работу в моем переопределении SaveChanges, таким образом я проигнорировал изменения из Updates и если бы это было Add the CreatedDate, будет установлено несколько строк позже.

Ответ 4

Как и Stephans Answer, но с Reflection, а также игнорирует всех пользователей ( внешние) обновления Создано/обновлено. Показать Gist

  public override int SaveChanges()
        {
            foreach (var entry in ChangeTracker.Entries().Where(x => x.Entity.GetType().GetProperty("CreatedTime") != null))
            {
                if (entry.State == EntityState.Added)
                {
                    entry.Property("CreatedTime").CurrentValue = DateTime.Now;
                }
                else if (entry.State == EntityState.Modified)
                {
                    // Ignore the CreatedTime updates on Modified entities. 
                    entry.Property("CreatedTime").IsModified = false;
                }

                // Always set UpdatedTime. Assuming all entities having CreatedTime property
                // Also have UpdatedTime
                // entry.Property("UpdatedTime").CurrentValue = DateTime.Now;
                // I moved this part to another foreach loop
            }

            foreach (var entry in ChangeTracker.Entries().Where(
                e => 
                    e.Entity.GetType().GetProperty("UpdatedTime") != null && 
                    e.State == EntityState.Modified || 
                    e.State == EntityState.Added))
            {
                entry.Property("UpdatedTime").CurrentValue = DateTime.Now;
            }

            return base.SaveChanges();
        }

Ответ 5

Accounts account;
account.Acct_JoinDate = DateTime.Now.ToUniversalTime();
data.Accounts.Add(account);
data.SaveChanges();

Почему бы не указать временную метку при создании модели? Подобно этим данным.

Ответ 6

В настоящее время Code First не предоставляет механизм предоставления значений по умолчанию для столбцов.

Вам необходимо вручную изменить или создать базовый класс для автоматического обновления CreateDate

public abstract class MyBaseClass
{
    public MyBaseClass()
    {
        CreatedDate = DateTime.Now;
    }
    public Datetime CreatedDate { get; set; }
}