namespace EnVisage { using System; using System.Collections.Generic; using System.Data.Entity; using System.Data.Entity.Core.Objects; using System.Data.Entity.Core.Objects.DataClasses; using System.Data.Entity.Infrastructure; using System.IO; using System.Runtime.Serialization; using System.Xml; using System.Xml.Linq; using System.Linq; using System.Data.Entity.Core; using NLog; using Microsoft.AspNet.Identity; using System.Web; public partial class EnVisageEntities : DbContext { public ObjectContext ObjectContext() { return (this as IObjectContextAdapter).ObjectContext; } List historyList = new List(); //partial void OnContextCreated() //{ // this.ObjectContext().SavingChanges += new EventHandler(projectionsEntities_SavingChanges); //} public override int SaveChanges() { historyList.Clear(); List changes = this.ObjectContext().ObjectStateManager.GetObjectStateEntries(EntityState.Modified).ToList(); changes.AddRange(this.ObjectContext().ObjectStateManager.GetObjectStateEntries(EntityState.Added).ToList()); changes.AddRange(this.ObjectContext().ObjectStateManager.GetObjectStateEntries(EntityState.Deleted).ToList()); foreach (ObjectStateEntry stateEntryEntity in changes) { if (!stateEntryEntity.IsRelationship && stateEntryEntity.Entity != null && !(stateEntryEntity.Entity is History) && ( stateEntryEntity.Entity is Project || stateEntryEntity.Entity is Scenario || stateEntryEntity.Entity is AspNetUser || stateEntryEntity.Entity is AspNetRole || stateEntryEntity.Entity is ProjectAccess || stateEntryEntity.Entity is Security || stateEntryEntity.Entity is Expenditure || stateEntryEntity.Entity is ExpenditureCategory || stateEntryEntity.Entity is Expenditure2Expenditure || stateEntryEntity.Entity is FeeCalculation || stateEntryEntity.Entity is Rate || stateEntryEntity.Entity is Company || stateEntryEntity.Entity is Client || stateEntryEntity.Entity is UOM || stateEntryEntity.Entity is EnVisage.Type || stateEntryEntity.Entity is EnVisage.Status || stateEntryEntity.Entity is FiscalCalendar || stateEntryEntity.Entity is GLAccount || stateEntryEntity.Entity is ScenarioDetail || stateEntryEntity.Entity is Company2Client || stateEntryEntity.Entity is Company2View || stateEntryEntity.Entity is Attachment ) ) {//is a normal entry, not a relationship History history = this.HistoryFactory(stateEntryEntity); historyList.Add(history); } } if (historyList.Count > 0) { List ids = new List(); foreach (var history in historyList) { if (!ids.Contains(history.Id)) { ids.Add(history.Id); this.Histories.Add(history); } else { history.Id = Guid.NewGuid(); if (!ids.Contains(history.Id)) this.Histories.Add(history); } } } return base.SaveChanges(); } /// /// This is a temporary method for reducing dramatic history record amounts for scenario details and similar entities - use with caution /// [Obsolete("This is a temporary method for reducing dramatic history record amounts for scenario details and similar entities - use with caution")] public int SaveChangesWithoutHistory() { return base.SaveChanges(); } private History HistoryFactory(ObjectStateEntry entry) { History history = new History(); var objectStateEntry = this.ObjectContext().ObjectStateManager.GetObjectStateEntry(entry.Entity); history.Id = Guid.NewGuid(); if (entry.State != EntityState.Added) history.EntityId = new Guid(objectStateEntry.EntityKey.EntityKeyValues[0].Value.ToString()); history.TimeStamp = DateTime.Now; try { history.ModifiedBy = new Guid(HttpContext.Current.User.Identity.GetID()); } catch(Exception) { history.ModifiedBy = Guid.Empty; } history.ModificationType = entry.State.ToString(); history.EntityType = entry.Entity.GetType().Name.Split('_')[0]; history.XML = GetEntryValueInString(entry, true); return history; } private string GetEntryValueInString(ObjectStateEntry entry, bool isOrginal) { XmlDocument doc = new XmlDocument(); XmlElement el = (XmlElement)doc.AppendChild(doc.CreateElement("Entity")); XmlElement modified = null; el.SetAttribute("type", entry.Entity.GetType().Name.Split('_')[0]); var props = entry.Entity.GetType().GetProperties(); if (entry.State == EntityState.Modified || entry.State == EntityState.Deleted) foreach (var elem in props) { var name = elem.Name; int i = -1; try { i = entry.OriginalValues.GetOrdinal(elem.Name); } catch { } if (i >= 0) { var val = Convert.ToString(entry.OriginalValues[entry.OriginalValues.GetOrdinal(elem.Name)]); el.AppendChild(doc.CreateElement(name)).InnerText = Convert.ToString(val); if (entry.State == EntityState.Modified && val != Convert.ToString(elem.GetValue(entry.Entity))) { if (modified == null) modified = (XmlElement)el.AppendChild(doc.CreateElement("Modified")); modified.AppendChild(doc.CreateElement(name)).InnerText = Convert.ToString(elem.GetValue(entry.Entity)); } } } if (entry.State == EntityState.Added) foreach (var elem in props) { if (elem.Name == "Id") { var val = elem.GetValue(entry.Entity); el.AppendChild(doc.CreateElement(elem.Name)).InnerText = Convert.ToString(val); } } return doc.OuterXml; } 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 List GetHistory(Guid Id) { return (from s in this.Histories where (s.EntityId == Id) select s).ToList(); } public void RecoverFromHistory(Guid HistoryId) { var history = (from s in this.Histories where (s.Id == HistoryId) select s).FirstOrDefault(); object recovered = GetEntityFromXML(history.XML, "Show"); EditEntity(this, (EntityObject)recovered); } public static object GetEntityFromXML(string ObjectInXML, string typeName) { XDocument doc = XDocument.Parse(ObjectInXML); var type = doc.Root.Attribute("type").Value; var id = new Guid(doc.Root.Element("Id").Value); System.Type entityType = System.Type.GetType(type); var entity = Activator.CreateInstance(entityType); var props = entityType.GetProperties(); foreach (var prop in props) { if (prop.Name == "Modified") continue; var name = prop.Name; var val = doc.Root.Element(name).Value; if (null != prop && prop.CanWrite) prop.SetValue(entity, val, null); } return entity; } public static void EditEntity(EnVisageEntities context, EntityObject entity) { // Define an ObjectStateEntry and EntityKey for the current object. EntityKey key; object originalItem; // Get the detached object's entity key. if (entity.EntityKey == null) { // Get the entity key of the updated object. key = context.ObjectContext().CreateEntityKey(entity.GetType().Name, entity); } else { key = entity.EntityKey; } try { // Get the original item based on the entity key from the context // or from the database. if (context.ObjectContext().TryGetObjectByKey(key, out originalItem)) {//accept the changed property // Call the ApplyPropertyChanges method to apply changes // from the updated item to the original version. context.ObjectContext().ApplyCurrentValues(key.EntitySetName, entity); } else { context.ObjectContext().AddObject(entity.GetType().Name, entity); } } catch (Exception ex) { var sb = DateTime.Now.ToString() + ": " + ex.Message; var logger = LogManager.GetCurrentClassLogger(); if (logger != null) logger.Fatal(sb.ToString()); } } } }