实体框架代码第一个通用数据库审计字段

时间:2013-05-24 11:51:36

标签: c# entity-framework oop entity-framework-5

我是Entity Framework的新手,过去我直接使用Enterprise Library或ADO.NET将模型映射到数据库表。我使用的一种模式是将我的公共审计字段放在基类中的每个表中,然后为每个对象继承该基类。

我采取两个步骤来保护两个字段(Created,CreatedBy):

  1. 在Base Enitity上设置一个无参数构造函数私有,并创建第二个需要Created和CreatedBy的构造函数在创建时传递。
  2. 将setter设为Private,以便在创建对象后无法更改这些值。
  3. 基类:

    using System;
    
    namespace App.Model
    {
        [Serializable()]
        public abstract class BaseEntity
        {
            public bool IsActive { get; private set; }
            public DateTimeOffset Created { get; private set; }
            public string CreatedBy { get; private set; }
            public DateTimeOffset LastUpdated { get; protected set; }
            public string LastUpdatedBy { get; protected set; }
    
            private BaseEntity() { }
    
            protected BaseEntity(DateTimeOffset created, string createdBy)
            {
                IsActive = true;
                Created = created;
                CreatedBy = createdBy;
                LastUpdated = created;
                LastUpdatedBy = createdBy;
            }
        }
    }
    

    继承类:

    using System;
    
    namespace App.Model
    {
        [Serializable()]
        public class Person : BaseEntity
        {
            public int Id { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public string Email { get; set; }
    
            public Person(DateTimeOffset created, string createdBy) : 
                base(created, createdBy) {  }
        }
    }
    

    我遇到了两个问题。 EF需要无参数构造函数来创建对象。 EF不会创建具有私有setter的数据库列。

    我的问题是,如果有更好的方法来实现我的目标:

    1. 要求在实例化时填充Created和CreatedBy的值。
    2. 无法更改Created和CreatedBy的值。

2 个答案:

答案 0 :(得分:5)

您可以使用接受字符串createdBy的构造函数实例化上下文。然后覆盖SaveChanges()

public override int SaveChanges()
{
    foreach( var entity in ChangeTracker.Entries()
                                        .Where(e => e.State == EntityState.Added)
                                        .Select (e => e.Entity)
                                        .OfType<BaseEntity>())
    {
        entity.SetAuditValues(DateTimeOffset.Now, this.CreatedBy);
    }
    return base.SaveChanges();
}

SetAuditValues()

internal void SetAuditValues(DateTimeOffset created, string createdBy)
{
    if (this.Created == DateTimeOffset.MinValue) this.Created = created;
    if (string.IsNullOrEmpty(this.CreatedBy)) this.CreatedBy = createdBy;
}

从数据库中实现实体后,当有人调用SetAuditValues时,不会覆盖这些值。

答案 1 :(得分:0)

您不应该尝试直接在实体/数据层上控制访问权限,而应该在应用程序层中执行此操作。通过这种方式,您可以更好地控制用户可以执行的操作。

此外,您可能希望将审核记录存储在另一个表中,而不是在每个表上重复审核字段。首先使用代码很容易做到这一点:

public class AuitRecord
{
    public bool IsActive { get; set; }
    public DateTimeOffset Created { get; set; }
    public string CreatedBy { get; set; }
    public DateTimeOffset LastUpdated { get; set; }
    public string LastUpdatedBy { get; set; }
}

然后,您可以将基类与审计记录链接到它:

public abstract class BaseEntity
{
    public AuditRecord Audit { get; set; }
}

最后是你的实体

public class Person : BaseEntity
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
}

您无法通过以下方式访问审核数据:

Person.Audit.IsActive