Implementing OnContextCreated for auditing by assigning SaveChanges an eventhandler using EF 4.1 DBContext
===

I have tried many different ways and looked at different posts, but still haven't come across a solution for this way of auditing. Below is my DBContext template file. I customised it by adding the OnContextCreated() partial method and assign the SavingChanges event to my OnSavingChanges eventhandler.




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; }
    }
}

However, when I compile, i get the error message that:

Error	1	'ARSystem.Models.ARSEntities.OnModelCreating(System.Data.Entity.DbModelBuilder)': no suitable method found to override	C:\Users\mngum\Documents\Visual Studio 2010\Projects\ARSystem\ARSystem\Models\ARSystem.Context.cs	35	33	ARSystem

I cannot see the OnContextCreated method in the DBContext metadata class but i can find it in the edmx designer. Please let me know how i can implement the OnContextCreated() method such that I can override the SavingChanges event for auditing purposes.