8

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

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

  1. 在基本实体上拥有一个私有的无参数构造函数,并创建第二个需要在创建时传递 Created 和 CreatedBy 的构造函数。
  2. 将设置器设为私有,以便在创建对象后无法更改值。

基类:

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 的数据库列。

我的问题是是否有更好的方法来实现我的 EF 目标:

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

2 回答 2

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.

于 2013-05-24T14:48:13.143 回答
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 
于 2013-05-24T12:15:29.250 回答