设置更新日期

Set updated date

我先用EF数据库

我有一个 table,其中有一个 'date updated' 列。当记录在其中更新时,它需要具有当前日期时间。我正在使用 EF,所以我无法编辑任何自动生成的模型 classes。我不想编辑 T4 模板,因为我认为如果我升级 EF

它将被覆盖

为了解决一个不同的问题,我遵循了这个:http://www.ozkary.com/2015/01/add-data-annotations-to-entity.html 生成一个 'buddy' class 据我所知只是扩展了自动生成的 EF class

然后我按照这个答案:set default value in class constructor C# 似乎显示了我需要的解决方案。但是当我测试时,DateUpdated 没有改变

这是我自动生成的 class 的一部分。你可以在这里看到DTUpdated

namespace bt2.Models
{
    using System;
    using System.Collections.Generic;

    public partial class Task
    {
        public int Task_ID { get; set; }
        public int TaskType_ID { get; set; }
        public int Emp_ID { get; set; }
        public System.DateTime DTInserted { get; set; }
        public System.DateTime DTUpdated { get; set; }

        public virtual TaskType TaskType { get; set; }
        public virtual Task Tasks1 { get; set; }
        public virtual Task Task1 { get; set; }
    }
}

这是我的 'buddy' class,我在其中尝试向自动生成的 class:

添加额外的代码
namespace bt2.Models
{
    [MetadataType(typeof(TaskMD))]
    public partial class Task
    {
    }

    internal sealed class TaskMD
    {
        [DisplayName("ID")]
        public int Task_ID { get; set; }

        [DisplayName("Task Type")]

        public int TaskType_ID { get; set; }

        public System.DateTime DTUpdated {
            get { return DateTime.Now; }
            set { this.DTUpdated = value; }
        }
    }

据我所知,这第二个 class 是对原始 class

的扩展

我想解决我的问题,但我也想在这里更详细地了解发生了什么。

我不完全确定那里发生了什么,但这里有一些建议:

  1. 您可以为每个实体和实体中的每个 属性 生成属性。这有点棘手,您甚至可以为实体生成密钥。您可以取消扩展 class 和创建元数据。这反映了您的数据库模式。我在我的项目中使用了这种方法并且有效。

  2. 使用 T4 模板自动生成文件是一次性事件(除非您进行了一些更改并且想要 re-generate 所有实体)。因此,建议断开连接并仅使用项目中生成的实体。

因为上下文 class 是部分 class 您可以创建自己的部分 class 并重载 SaveChanges 方法。

在此方法中,您可以使用反射获取 DTUpated 属性 并设置更新日期时间值。 (如果 属性 的名称相同,如果名称不相同,则将名称作为参数传入)

类似下面的内容。

public partial class TBCompanyEntities
{

    public void SaveChanges(object o)
    {
        try
        {
            var propertyInfo = o.GetType().GetProperty("DTUpdated");

            // This hasn't been tested by me yet - will test and update if need changes
            if(propertyInfo != null)
                propertyInfo.SetValue(o, Convert.ChangeType(DateTime.UtcNow, propertyInfo.PropertyType), null);
        }
        catch (Exception ex)
        {
            //  Logging.Log.Error(ex);
        }

        base.SaveChanges();

    }
}

然后在你的代码中而不是调用 dbContxt.SaveChanges(); 你可以调用

dbContext.SaveChanges(YOUR_ENTITY_OBJECT);

示例:

            using (var dbContext = new TBCompanyEntities())
            {
                // Entity with DTUpdated
                var notification = dbContext.NotificationArchives.First(s => s.iNotificationId == 1);
                notification.bIsRead = true;
                dbContext.SaveChanges(notification);

                //Entity without DTUpdated
                var asset = dbContext.Assets.First(s => s.iAssetId == 1);
                asset.iDriverId = null;
                dbContext.SaveChanges();
            }

编辑:

覆盖是指被覆盖方法的参数与基本方法相同。

所以你必须这样做:

public partial class TBCompanyEntities
{

    public override void SaveChanges()
    {
       //TODO: Here you will have to detect which entity has been modified/updated.
       // This should be possible, by using the Track Entity Changes features

               var modifiedEntities = ChangeTracker.Entries()
        .Where(p => p.State == EntityState.Modified).ToList();


        base.SaveChanges();

    }
}

这是一个很好的 link 覆盖,作者在其中跟踪对实体的更改,然后创建一个日志。 (如审计日志)

https://www.exceptionnotfound.net/entity-change-tracking-using-dbcontext-in-entity-framework-6/