tutorial - Agregar CreatedDate a una entidad usando Entity Framework 5 Code First
mvc 5 with entity framework (6)
Así es como lo hice:
[DatabaseGenerated(DatabaseGeneratedOption.Computed)]
public DateTime CreatedDate{ get; set; }
en el método Up () de mi migración:
AddColumn("Agents", "CreatedDate", n => n.DateTime(nullable: false, defaultValueSql: "GETUTCDATE()"));
Estoy tratando de agregar una propiedad CreatedDate
a las entidades de mi modelo y estoy usando el código EF5 primero. Quiero que esta fecha no se modifique una vez establecida, quiero que sea una fecha UTC. NO quiero usar un constructor, ya que tengo muchas entidades en mi modelo que quiero heredar de una clase abstracta que contiene la propiedad CreatedDate
, y no puedo imponer un constructor con una interfaz.
He intentado diferentes anotaciones de datos y he intentado escribir un inicializador de base de datos que recogería un tipo de entidad específica y escribiera una restricción getdate()
con un valor predeterminado getdate()
para el nombre de getdate()
y el nombre de getdate()
correctos, pero no he podido escribir ese código correctamente.
No me remita al AuditDbContext - Entity Framework Auditing Context ni a las herramientas EntityFramework.Extended , ya que no hacen lo que necesito aquí.
ACTUALIZAR
My CreatedDate
es nula en SaveChanges()
porque estoy pasando un ViewModel a mi vista, que correctamente no tiene una propiedad de auditoría llamada CreatedDate
. E incluso si pasé el modelo a mi vista, no estoy editando o almacenando CreatedDate
en la vista.
Leí here que podría agregar el [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
y esto le diría a EF que almacene la fecha de CreatedDate
correctamente después de Insertar y actualizar, pero que no permita que mi aplicación la cambie: pero solo obtengo un Cannot insert explicit value for identity column in table when IDENTITY_INSERT is set to OFF
error de Cannot insert explicit value for identity column in table when IDENTITY_INSERT is set to OFF
al agregar este atributo.
Estoy a punto de cambiar a EF Model First porque este simple requisito de base de datos es ridículo de implementar en Code First.
Bien, el problema principal aquí fue que CreatedDate se actualizaba cada vez que llamaba SaveChanges y, como no pasaba CreatedDate a mis vistas, se estaba actualizando a NULL o MinDate por Entity Framework.
La solución fue simple, sabiendo que solo necesito establecer CreatedDate cuando EntityState.Added, solo configuré mi entity.CreatedDate.IsModified = false antes de realizar cualquier trabajo en mi reemplazo de SaveChanges, de esa manera ignoré los cambios de las actualizaciones y si era un Add the CreatedDate se establecería unas líneas más tarde.
Code First no proporciona actualmente un mecanismo para proporcionar valores predeterminados de columna.
Deberá modificar manualmente o crear una clase base para la actualización automática CreatedDate
public abstract class MyBaseClass
{
public MyBaseClass()
{
CreatedDate = DateTime.Now;
}
public Datetime CreatedDate { get; set; }
}
Reemplace el método SaveChanges en su contexto:
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();
}
Actualizado debido a los comentarios : solo las Entidades recién agregadas tendrán su Fecha establecida.
Similar a la Respuesta de Stephans pero con Reflection y también ignora todas las actualizaciones creadas / actualizadas (externas) de los usuarios. Mostrar 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();
}
Accounts account;
account.Acct_JoinDate = DateTime.Now.ToUniversalTime();
data.Accounts.Add(account);
data.SaveChanges();
¿Por qué no dar la marca de tiempo sobre la creación del modelo? Similar a estas cuentas aquí.