Добавление 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.
Ответы
Ответ 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; }
}