在 MVC 5 ASP.NET 中创建日期和修改日期

本文关键字:创建日期 修改 日期 NET MVC ASP | 更新日期: 2023-09-27 18:32:30

我正在做一个代码优先项目,我需要数据库来处理DateCreatedDateModified

该应用程序在 IIS Express 上运行,在开发计算机上使用 LocalDB,并将在部署服务器上使用 SQL Server 2012 和 IIS 7.5。

我有以下模型:

public class Person : IdentityUser {
  [Required]
  public string Name { get; set; }
  public Date DateOfBirth { get; set; }
  public string Address { get; set; }
  [DatabaseGeneratedOption.Identity]
  public Date DateCreated { get; set; }
  [DatabaseGeneratedOption.Identity]
  public Date DateModified { get; set; }
}

请列出配置数据库以处理事务元日期的确切步骤,例如需要在模型中设置的内容以及是否需要在数据库上下文配置器中采取任何操作。我正在寻找类似的东西:">你需要知道的关于 ASP.NET MVC日期处理的所有信息">,但不能触及这个方面。

提前谢谢。

在 MVC 5 ASP.NET 中创建日期和修改日期

我将从实体框架的角度考虑这个问题。

您基本上需要执行以下操作:

1-我将定义一个像ITrackable接口这样的接口,如果这些模型需要跟踪DateCreated和DateModified的端口,则让我的模型实现该接口。

2-以某种方式,您的模型知道它是否是已添加/已修改实体,因为这将决定要设置的属性(对于已添加实体和仅针对已修改实体的修改日期(。

3-在实体框架中使用DbContext添加一个扩展方法,当您尝试通过SaveChanges或SaveChangesAsync保存实体时需要调用该方法,此方法将遍历跟踪的实体并根据实体的状态设置DateCreated和DateModified属性。

因此,您的模型将如下所示:

public class Person : IdentityUser, ITrackable
{
    [Required]
    public string Name { get; set; }
    public Date DateOfBirth { get; set; }
    public string Address { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateModified { get; set; }
}

ITrackable看起来像什么样子

public interface ITrackable
{
    public DateTime DateCreated { get; set; }
    public DateTime DateModified { get; set; }
}

扩展方法将是这样的:

internal static class ContextHelper
{
    internal static void SyncObjectsStatePreCommit(this DbContext dbContext)
    {
        foreach (var dbEntityEntry in dbContext.ChangeTracker.Entries())
        {
            // do any other stuff you want.
            // ..
            // ..
            // work with ITrackable entities
            var trackableObject = dbEntityEntry.Entity as ITrackable;
            // we need to set/update trackable properties
            if (trackableObject == null)
            {
                continue;
            }
            var dateTime = DateTime.Now;
            // set createddate only for added entities
            if (entityState.ObjectState == ObjectState.Added)
            {
                trackableObject.CreatedDate = dateTime;
            }
            // set LastUpdatedDate for any case other than Unchanged
            if (entityState.ObjectState != ObjectState.Unchanged)
            {
                trackableObject.ModifiedDate = dateTime;
            }
        }
    }
}

例如,现在在您的 dbContext Save 方法中,您需要调用此方法来设置所有这些属性。

public override Task<int> SaveChangesAsync()
{
    this.SyncObjectsStatePreCommit();
    return base.SaveChangesAsync();
}

希望有帮助。

我发现上面的答案有点令人困惑,但是我认为更直接的解决方案是覆盖本博客中所述的SaveChanges方法

此解决方案还使用 ITrackable 接口,当触发SaveChanges时,它会检查Entity是否实现了此接口:

public override System.Threading.Tasks.Task<int> SaveChangesAsync()
{
    foreach (var auditableEntity in ChangeTracker.Entries<ITrackableEntity>())
    {
        if (auditableEntity.State == EntityState.Added ||
            auditableEntity.State == EntityState.Modified)
        {
            // implementation may change based on the useage scenario, this
            // sample is for forma authentication.
            string currentUser = HttpContext.Current.User.Identity.GetUserId();
            DateTime currentDate = SiteHelper.GetCurrentDate();
            // modify updated date and updated by column for 
            // adds of updates.
            auditableEntity.Entity.ModifiedDateTime = currentDate;
            auditableEntity.Entity.ModifiedUserId = currentUser;
            // pupulate created date and created by columns for
            // newly added record.
            if (auditableEntity.State == EntityState.Added)
            {
                auditableEntity.Entity.CreatedDateTime = currentDate;
                auditableEntity.Entity.CreatedUserId = currentUser;
            }
            else
            {
                // we also want to make sure that code is not inadvertly
                // modifying created date and created by columns 
                auditableEntity.Property(p => p.CreatedDateTime).IsModified = false;
                auditableEntity.Property(p => p.CreatedUserId).IsModified = false;
            }
        }
    }
    return base.SaveChangesAsync();
}

我相信实体框架文档明确指出:

警告

与默认值或计算列不同,我们不指定如何将生成值;这取决于在正在使用的数据库提供程序上。数据库提供程序可以自动为某些属性类型设置值生成,但其他属性类型可能需要手动设置值的生成方式。例如,在 SQL 上服务器,当 GUID 属性配置为在添加时生成的值时,提供程序在客户端自动执行价值生成,使用用于生成最佳顺序 GUID 值的算法。然而指定"在日期时间添加时生成的值"属性将没有效果(请参阅下面的日期时间值生成部分(。同样,配置为在添加或更新并标记为并发令牌使用行版本进行设置数据类型,以便在数据库中自动生成值。但是,指定"添加时生成的值"不起作用。

这是下载时文档的第 284 页(假设您的部分不重复某些部分(。文档继续说

注意

根据所使用的数据库提供程序,可能会生成值客户端由 EF 或在数据库中。如果该值由数据库,则 EF 可能会在添加实体时分配一个临时值到上下文;然后,此临时值将替换为保存更改期间数据库生成的值。欲了解更多信息,请参阅有关临时值的文档。

无论如何,RTFM!