Entity Framework:设置更新时间戳。

11

我们所有的数据库表都有UpdateUserID和UpdateTS。如果我的实体有更改,我希望设置这个值。是否可以有一种条件方式来立即更新它呢?

如果我在代码中手动设置UpdateTS,则会认为我的实体已更改,并始终更新对象。

3个回答

8
以下是另外两个想法的实现,需要注意以下几点:
  • 确保您创建了自动检测更改的代理或者在调用SaveChanges()之前手动检测更改。否则,对象状态将为EntityState.Unmodified,并且最后修改的时间戳不会更新。
  • 我还扩展了代码以在对象首次创建(EntityState.Added)时设置最后修改的时间戳。

代码

public interface IHasLastModified
{
    DateTime? LastModified { get; set; }
}

public class MyClass : IHasLastModified
{
    public virtual int Id { get; set; }

    public virtual string SomeOtherProperty { get; set; }

    public virtual DateTime? LastModified { get; set; }
}

public class MyContext : DbContext
{
    public override int SaveChanges()
    {            
        DateTime now = DateTime.UtcNow;
        foreach (ObjectStateEntry entry in (this as IObjectContextAdapter).ObjectContext.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Modified))
        {
            if (!entry.IsRelationship)
            {
                IHasLastModified lastModified = entry.Entity as IHasLastModified;
                if (lastModified != null)
                    lastModified.LastModified = now;
            }
        }

        return base.SaveChanges();
    }

1
我使用了类似的解决方案,但是我还需要能够处理无代理实体(这些实体被上述代码忽略)。我提出了修改答案以支持此功能的建议,但被拒绝了... - Anders
2
@Anders:你可以发布自己的答案并进行修改。你可以引用我的答案,并指出你的答案如何正确处理无代理实体。 - Eric J.

7

在调用 context.SaveChanges() 之前,我会调用这个扩展方法:

public static void SetLastModified(this ObjectContext context, DateTime dateTime)
{
    DateTime now = DateTime.UtcNow;
    foreach (ObjectStateEntry entry in context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified))
    {
        if (!entry.IsRelationship)
        {
            IHasLastModified lastModified = entry.Entity as IHasLastModified;
            if (lastModified != null)
                lastModified.LastModified = now;
        }
    }
}

我可以轻松调用这段代码,因为我已经将ObjectContext封装在一个仓储类中。如果你直接使用它,你可以将ObjectContext.SavingChanges事件连接起来实现类似的功能。


1
尝试按照此处列出的方式进行操作,但在使用IHasLastModified时遇到了困难。lastModified始终只返回null。您能否发布一下您对此接口的代码,或者告知如何使您的实体继承它? - Martin
2
我确保我的数据对象有一个名为LastModified的DateTime属性,然后在部分类中实现接口(这样代码生成就不会将其丢弃)。因为属性已经存在,所以没有需要实现的代码。 - Sander Rijken

1
我无法使用 @eric-j 提出的解决方案,它只在创建新对象时设置日期,而不是在更新时设置。
我找到了 这个解决方案 并进行了修改以使其看起来相似。尝试过它,效果非常好。
public override int SaveChanges()
{
    var now = DateTime.UtcNow;

    var entries = ChangeTracker
        .Entries()
        .Where(e => e.State == EntityState.Added || e.State == EntityState.Modified);

    foreach (var entry in entries)
    {
        if (entry.Entity is IHasLastModified lastModified)
        {
            lastModified.LastModified = now;
            if (entry.State == EntityState.Added)
            {
                lastModified.CreatedDate = now;
            }
        }
    }

    return base.SaveChanges();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接