我是Entity Framework的新手,过去我直接使用Enterprise Library或ADO.NET将模型映射到数据库表。我使用的一种模式是将我的公共审计字段放在基类中的每个表中,然后为每个对象继承该基类。
我采取两个步骤来保护两个字段(Created,CreatedBy):
基类:
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的数据库列。
我的问题是,如果有更好的方法来实现我的目标:
答案 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