c# - DbDataRecord - entry.CurrentValues 和 entry.originalValues 相同

标签 c# .net asp.net-mvc-3 entity-framework

我正在使用 Entity Framework 4.1,并且我有我的 DbContext Override SaveChanges 来审核属性更改。从“GetEntryValueInString”返回空值的代码。它的原因是“if (entry.Entity is EntityObject)”这个条件在所有情况下都失败了。如果我在评论条件时遇到另一个问题,例如 CurrentValues 和 OriginalValues 变得相同。

namespace mymodel
 {
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Objects;
using System.Data.Objects.DataClasses;
using System.IO;
using System.Reflection;
using System.Runtime.Serialization;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;

public partial class DbEntities : DbContext
{
    public DbEntities ()
        : base("name=DbEntities ")
    {
    }

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

    public DbSet<DBAudit> DBAudits { get; set; }

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

    public enum AuditActions
    {
        I,
        U,
        D
    }

    public override int SaveChanges()
    {

        ChangeTracker.DetectChanges(); // Important!

        ObjectContext ctx = ((IObjectContextAdapter)this).ObjectContext;


        IEnumerable<ObjectStateEntry> changes = ctx.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);
            }
        }

        return base.SaveChanges();
    }
    private DBAudit AuditTrailFactory(ObjectStateEntry entry, string UserName)
    {
        DBAudit audit = new DBAudit();

        audit.UpdateDate = DateTime.Now;
        audit.TableName = entry.EntitySet.Name;
        audit.UserId = 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.TableName = 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<Area> Areas { get; set; }
    public DbSet<Country> Countries { get; set; }
    public DbSet<Event> Events { get; set; }
    public DbSet<Group> Groups { get; set; }
    public DbSet<Holiday> Holidays { get; set; }
    public DbSet<Location> Locations { get; set; }
    public DbSet<Notification> Notifications { get; set; }
    public DbSet<Receipt> Receipts { get; set; }
    public DbSet<Report> Reports { get; set; }
    public DbSet<Role> Roles { get; set; }
    public DbSet<State> States { get; set; }
    public DbSet<Store> Stores { get; set; }
    public DbSet<TimeZone> TimeZones { get; set; }
}

最佳答案

public partial class DbEntities
{
    public enum AuditActions
    {
        I,
        U,
        D
    }
    public override int SaveChanges()
    {

            ChangeTracker.DetectChanges(); // Important!

            ObjectContext ctx = ((IObjectContextAdapter)this).ObjectContext;

            IEnumerable<ObjectStateEntry> changes = ctx.ObjectStateManager.GetObjectStateEntries(EntityState.Added | EntityState.Deleted | EntityState.Modified);
            foreach (ObjectStateEntry stateEntryEntity in changes)
            {
                if (stateEntryEntity.EntitySet.Name != "MobileLoginDatas" && stateEntryEntity.EntitySet.Name != "SystemLookUps")//eliminate these tables
                {
                    if (SessionData.userId != null && SessionData.userId != 0) //execute only after user login
                    {
                        if (!stateEntryEntity.IsRelationship &&
                                stateEntryEntity.Entity != null &&
                                    !(stateEntryEntity.Entity is DBAudit))
                        {
                            DBAudit audit = new DBAudit();
                            audit.RevisionStamp = DateTime.Now;
                            audit.UserId = SessionData.userId;
                            audit.TableName = stateEntryEntity.EntitySet.Name;
                            audit.IPAddress = SessionData.clientIpAddress;

                            if (stateEntryEntity.State == EntityState.Added)
                            {//entry is Added 
                                audit.Data = DictionaryToJsonConverter(GetEntryValueString(stateEntryEntity, false));

                                audit.Action = AuditActions.I.ToString();
                            }
                            else if (stateEntryEntity.State == EntityState.Deleted)
                            {//entry in deleted
                                audit.Data = DictionaryToJsonConverter(GetEntryValueString(stateEntryEntity, true));
                                audit.Action = AuditActions.D.ToString();
                            }
                            else
                            {//entry is modified
                                audit.Data = DictionaryToJsonConverter(GetEntryValueString(stateEntryEntity, false));
                                audit.Action = AuditActions.U.ToString();
                            }
                            this.Entry(audit).State = System.Data.EntityState.Added;
                        }
                    }
                }
            }


      //  }
        return base.SaveChanges();
    }
    ///convert the data to json
    string DictionaryToJsonConverter(Dictionary<String, Object> dict)
    {
        var entries = dict.Select(d =>
            string.Format("'{0}': {1}", d.Key, string.Join(",", d.Value)));
        return "{" + string.Join(",", entries) + "}";
    }
    private Dictionary<string, object> GetEntryValueString(ObjectStateEntry entry, Boolean isOriginal)
    {
        var keyValues = new Dictionary<string, object>();
        var values = (IDataRecord) null;
        if (isOriginal)
        {
            values = entry.OriginalValues;
        }
        else
        {
            values = entry.CurrentValues;
        }
        for (int i = 0; i < values.FieldCount; i++)
        {
            keyValues.Add(values.GetName(i), values.GetValue(i));
        }
        return keyValues;
    }
}

关于c# - DbDataRecord - entry.CurrentValues 和 entry.originalValues 相同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20211041/

相关文章:

asp.net-mvc - 使用 ASP.NET MVC3 进行客户端模型级或表单级验证

asp.net-mvc - 从 Ajax Post 操作加载 jqGrid

c# - 如何从 C# 数组中删除重复项?

c# - TCP程序包大于MTU时,C#Socket.Receive()发生故障

javascript - 使用单独的 js 文件并在其中使用 Url Helpers 与 ASP.NEt MVC 3 和 Razor View Engine

C# JavaScriptSerializer 序列化接口(interface)中不存在但存在于原始对象中的字段

c# - 具有大数据集的不完整 HttpWebResponse

c# - 为什么 WebView2 渲染一个只有 1 行文本的基本页面那么慢?

c# - 绑定(bind)到项目而不是列表框中的属性

C#文本框更新sql数据库