2012-07-24 69 views
4

通过分配SaveChanges事件处理程序来实现OnContext创建用于审计我已经尝试了许多不同的方法并查看了不同的帖子,但仍未遇到这种审计方式的解决方案。以下是我的DBContext模板文件。我通过添加OnContextCreated()部分方法来定制它,并将SavingChanges事件分配给我的OnSavingChanges事件处理程序。使用EF 4.1 DBContext

namespace ARSystem.Models 
{ 
    public partial class ARSEntities : ObjectContext 
    { 
     public ARSEntities() 
      : base("name=ARSEntities") 
     { 
     } 

     protected override void OnModelCreating(DbModelBuilder modelBuilder) 
     { 
      throw new UnintentionalCodeFirstException(); 
     } 

     public string UserName { get; set; } 
     List<DBAudit> auditTrailList = new List<DBAudit>(); 

     public enum AuditActions 
     { 
      I, 
      U, 
      D 
     } 

     partial void OnContextCreated() 
     { 
      this.SavingChanges += new EventHandler(OnSavingChanges); 
     } 

     public void OnSavingChanges(object sender, EventArgs e) 
     { 
      IEnumerable<ObjectStateEntry> changes = this.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified); 
      foreach (ObjectStateEntry stateEntryEntity in changes) 
      { 
       if (!stateEntryEntity.IsRelationship && 
         stateEntryEntity.Entity != null && 
          !(stateEntryEntity.Entity is DBAudit)) 
       {//is a normal entry, not a relationship 
        DBAudit audit = this.AuditTrailFactory(stateEntryEntity, UserName); 
        auditTrailList.Add(audit); 
       } 
      } 

      if (auditTrailList.Count > 0) 
      { 
       foreach (var audit in auditTrailList) 
       {//add all audits 
        this.AddToDBAudit(audit); 
       } 
      } 
     } 

     private DBAudit AuditTrailFactory(ObjectStateEntry entry, string UserName) 
     { 
      DBAudit audit = new DBAudit(); 
      audit.AuditId = Guid.NewGuid().ToString(); 
      audit.RevisionStamp = DateTime.Now; 
      audit.TableName = entry.EntitySet.Name; 
      audit.UserName = UserName; 

      if (entry.State == EntityState.Added) 
      {//entry is Added 
       audit.NewData = GetEntryValueInString(entry, false); 
       audit.Actions = AuditActions.I.ToString(); 
      } 
      else if (entry.State == EntityState.Deleted) 
      {//entry in deleted 
       audit.OldData = GetEntryValueInString(entry, true); 
       audit.Actions = AuditActions.D.ToString(); 
      } 
      else 
      {//entry is modified 
       audit.OldData = GetEntryValueInString(entry, true); 
       audit.NewData = GetEntryValueInString(entry, false); 
       audit.Actions = AuditActions.U.ToString(); 

       IEnumerable<string> modifiedProperties = entry.GetModifiedProperties(); 
       //assing collection of mismatched Columns name as serialized string 
       audit.ChangedColumns = XMLSerializationHelper.XmlSerialize(modifiedProperties.ToArray()); 
      } 

      return audit; 
     } 

     private string GetEntryValueInString(ObjectStateEntry entry, bool isOrginal) 
     { 
      if (entry.Entity is EntityObject) 
      { 
       object target = CloneEntity((EntityObject)entry.Entity); 
       foreach (string propName in entry.GetModifiedProperties()) 
       { 
        object setterValue = null; 
        if (isOrginal) 
        { 
         //Get orginal value 
         setterValue = entry.OriginalValues[propName]; 
        } 
        else 
        { 
         //Get orginal value 
         setterValue = entry.CurrentValues[propName]; 
        } 
        //Find property to update 
        PropertyInfo propInfo = target.GetType().GetProperty(propName); 
        //update property with orgibal value 
        if (setterValue == DBNull.Value) 
        {// 
         setterValue = null; 
        } 
        propInfo.SetValue(target, setterValue, null); 
       }//end foreach 

       XmlSerializer formatter = new XmlSerializer(target.GetType()); 
       XDocument document = new XDocument(); 

       using (XmlWriter xmlWriter = document.CreateWriter()) 
       { 
        formatter.Serialize(xmlWriter, target); 
       } 
       return document.Root.ToString(); 
      } 
      return null; 
     } 

     public EntityObject CloneEntity(EntityObject obj) 
     { 
      DataContractSerializer dcSer = new DataContractSerializer(obj.GetType()); 
      MemoryStream memoryStream = new MemoryStream(); 

      dcSer.WriteObject(memoryStream, obj); 
      memoryStream.Position = 0; 

      EntityObject newObject = (EntityObject)dcSer.ReadObject(memoryStream); 
      return newObject; 
     } 

     public DbSet<Student> Students { get; set; } 
     public DbSet<User> Users { get; set; } 
     public DbSet<aspnet_Applications> aspnet_Applications { get; set; } 
     public DbSet<aspnet_Membership> aspnet_Membership { get; set; } 
     public DbSet<aspnet_Roles> aspnet_Roles { get; set; } 
     public DbSet<aspnet_SchemaVersions> aspnet_SchemaVersions { get; set; } 
     public DbSet<aspnet_Users> aspnet_Users { get; set; } 
     public DbSet<vw_aspnet_Applications> vw_aspnet_Applications { get; set; } 
     public DbSet<vw_aspnet_MembershipUsers> vw_aspnet_MembershipUsers { get; set; } 
     public DbSet<vw_aspnet_Roles> vw_aspnet_Roles { get; set; } 
     public DbSet<vw_aspnet_Users> vw_aspnet_Users { get; set; } 
     public DbSet<vw_aspnet_UsersInRoles> vw_aspnet_UsersInRoles { get; set; } 
     public DbSet<Cours> Courses { get; set; } 
     public DbSet<Enrollment> Enrollments { get; set; } 
     public DbSet<Modules> Modules { get; set; } 
     public DbSet<EnrollmentsByCourse> EnrollmentsByCourse { get; set; } 
     public DbSet<EnrollmentsByCourseAudit> EnrollmentsByCourseAudit { get; set; } 
     public DbSet<DBAudit> DBAudit { get; set; } 
    } 
} 

然而,当我编译,我得到的错误消息:

错误1 'ARSystem.Models.ARSEntities.OnModelCreating(System.Data.Entity.DbModelBuilder)':没有合适的方法发现重写C:\用户\ mngum \文件\的Visual Studio 2010 \项目\ ARSystem \ ARSystem \模型\ ARSystem.Context.cs 35 33 ARSystem

我不能看到的DbContext元数据类的OnContextCreated方法,但我可以在edmx设计器中找到它。请让我知道如何执行OnContextCreated()方法,以便我可以覆盖SavingChanges事件以进行审计。

回答

8

DbContext没有OnContextCreated事件,但这不是问题,因为您不需要它来实现相同。用DbContext代替SaveChanges方法是可覆盖的。因此,而不是你的OnSavingChanges事件处理程序的使用:

public override int SaveChanges() 
{ 
    // custom code... 

    return base.SaveChanges(); 
} 

每当调用ARSEntities.SaveChanges()你调用基DbContextARSEntities必须从当然DbContext得出的base.SaveChanges(),然后才能执行自定义操作此方法将被调用。)

您也可以访问底层ObjectContextDbContext

public override int SaveChanges() 
{ 
    var objectContext = ((IObjectContextAdapter)this).ObjectContext; 

    // use methods and properties of ObjectContext now like 
    // objectContext.ObjectStateManager, etc. 

    // custom code... 

    return base.SaveChanges(); 
} 

这里是一个类似的问题和答案变更审计与EF 4.1/DbContext

Entity Framework 4.1 DbContext Override SaveChanges to Audit Property Change

+0

你会如何编写单元测试的自定义代码? – 2016-04-28 16:03:02