反射很慢(慢是主观的),如果你想避免它,那么你需要删除如下代码:
Type type = entityEntry.Entity.GetType();
if (type.GetProperty("InsertedBy") != null)
即使速度不慢,上面的代码仍然是“有缺陷的”,因为程序员可能会错误地编写InsertBy
代替InsertedBy
。使用以下方法,可以在编译器的帮助下轻松避免这种情况。
使用接口并在所有需要审计的实体中实现它。
public interface IAuditable
{
string InsertedBy { get; set; }
// ... other properties
}
public class SomeEntity : IAuditable
{
public string InsertedBy { get; set; }
}
public class Auditor<TAuditable> where TAuditable : IAuditable
{
public void ApplyAudit(TAuditable entity, int userId)
{
// No reflection and you get compiler support
if (entity.InsertedBy == null)
{
// whatever
}
else
{
// whatever
}
}
}
正如评论中提到的,您将获得编译器支持并且不再使用反射。我什至会更进一步,不通过int userId
。我将带来用于计算的代码userId
并把它放在这个类中。这样,类就可以自给自足,客户不需要向其提供此信息。
Usage:
var e = new SomeEntity();
var auditor = new Auditor<SomeEntity>();
auditor.ApplyAudit(e, 1); // 1 is userId, I am just hardcoding for brevity
或者根据您的上下文使用它:
public override int SaveChanges()
{
var auditables = ChangeTracker.Entries().Where(e =>
e.State == System.Data.Entity.EntityState.Added || e.State == System.Data.Entity.EntityState.Modified)
.OfType<IAuditable>();
var auditor = new Auditor<IAuditable>();
foreach (var entry in auditables)
{
// 1 is userId, I am just hardcoding for brevity
auditor.ApplyAudit(entry, 1);
}
return base.SaveChanges();
}
这意味着所有可审计的实体都需要实施IAuditable
界面。 EF 为您的实体生成部分类,但不要修改这些部分类,因为下次运行自定义工具时,它将被清除。
相反,创建另一个同名的分部类并实现IAuditable
.
public partial class SomeEntity : IAuditable {}
更好的方法是创建自定义 T4 模板,以便它使用代码创建分部类: IAuditable
。请参见本文 http://matthidinger.com/archive/2010/02/09/customizing-the-entity-framework-t4-template-suppressing-code-analysis/如何做到这一点。