【问题标题】:How to get original values of an entity in Entity Framework?如何在实体框架中获取实体的原始值?
【发布时间】:2011-12-29 08:34:35
【问题描述】:

在 EF 4.0 中,如果我理解正确的话,Entity 中有两种类型的值:当前值和原始值。
我们可以通过调用 ApplyOriginalValues(TEntity) 方法来设置原始值,但是如何获取原始值呢?

【问题讨论】:

    标签: entity-framework-4 entity


    【解决方案1】:

    @Eranga 的答案对于 EF 5 已过时。出于某种原因,EF 5 在使用如下语句获取原始值时无法正常工作:

    var originalValues = context.Entry(myEntity).OriginalValues;
    

    我的工作解决方案使用来自DbSetAsNoTracking() 方法,如下例所示:

    var originalEntity = context.MyEntities.AsNoTracking().FirstOrDefault(me => me.MyEntityID == myEntity.MyEntityID);
    

    【讨论】:

    • 如何只获取修改后的值??
    • @AwaisMahmood 我认为这值得单独提问。
    • @CiganoMorrisonMendez.. 请访问这个.. 我已经问过这个问题但没有得到我的答案.. stackoverflow.com/questions/32737975/…
    • 请注意 AsNoTracking 将从数据库中读取实体。它可能已被并发任务更改,在这种情况下您可能会处理不正确的数据...
    • @0xDEADBEEF 没错。上下文不是线程安全的,在这种情况下使用事务很重要,但这是另一个主题。
    【解决方案2】:

    您可以通过ObjectStateEntry访问它们

    var originalValues = context
             .ObjectStateManager.GetObjectStateEntry(myEntity).OriginalValues;
    

    【讨论】:

    • originalValues 是 DbDataRecord 类型。如何将其转换为实体类型?
    • @Sun 它没有实体类型。您需要将值转换为适当的类型。例如var name = (string)originalValues["Name"];
    【解决方案3】:

    这可以进一步细化为:

    var originalEntity = context.MyEntities.AsNoTracking()
             .FirstOrDefault(me => me.MyEntityID == myEntity.MyEntityID);
    

    上面的Where,很好,不需要回复。

    【讨论】:

      【解决方案4】:
      var originalEntity = (EntityType)context.Entry(editEntity).OriginalValues.ToObject();
      

      对不起我的英语。 通过这种方式,您可以在不更改编辑值的情况下以对象实体的形式获取原始实体值。

      示例: 如果你喜欢编辑一个人,顶部的行看起来像这样

      var originalPerson = (Person)context.Entry(editPerson).OriginalValues.ToObject();
      

      【讨论】:

        【解决方案5】:

        我遇到了类似的问题,AsNoTracking 不是我的情况的选择,所以我想出了一些对我来说足够好的方法:首先“克隆”实体然后进行更改。

        public T Clone<T>(T entity)
          where T : class, new() {
        
          var clone = new T();
        
          var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)
            .Where(a => a.CanRead && 
                        a.CanWrite &&
                        a.GetMethod.IsFinal);
        
          foreach (var property in properties) {       
            property.SetValue(clone, property.GetValue(entity));
          }
        
          return clone;
        }
        

        然后将克隆与更改进行比较。

        public string GenerateChangeText<T>(T original, T current)
          where T : class, new() {
        
          var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy)
            .Where(a => a.CanRead &&
                        a.CanWrite &&
                        a.GetMethod.IsFinal);
        
          var changes = string.Empty;
        
          foreach (var property in properties) {
        
            var originalValue = property.GetValue(original);
            var currentValue = property.GetValue(current);
        
            if (originalValue == null && currentValue == null) continue;
            if ((originalValue != null && !originalValue.Equals(currentValue)) ||
               (currentValue != null && !currentValue.Equals(originalValue))) {
        
              changes += $" changed {property} from {original ?? "NULL"} to {current ?? "NULL"}.";
            }
          }
        
          return changes;
        }
        

        【讨论】:

          【解决方案6】:

          有几个版本的实体框架在使用中。

          我自己更喜欢 Code First 并且使用该 API 很简单

          _context.Entry(Entity).Reload();
          

          文档 https://msdn.microsoft.com/en-us/library/system.data.entity.infrastructure.dbentityentry.reload(v=vs.103).aspx

          较旧的 API 在 ObjectContext 上有一个 Refresh 方法,可以在某些用例中提供帮助

          ObjectContext.Refresh(RefreshMode.StoreWins, Entity);
          

          文档https://msdn.microsoft.com/en-us/library/bb896255(v=vs.110).aspx

          【讨论】:

            【解决方案7】:

            这个答案是指实体框架 6。在 EF 6 中有一个原始值和当前值https://msdn.microsoft.com/en-us/library/gg679512(v=vs.113).aspx 在寻找并没有找到一个好的答案之后,我想出了以下测试函数,并认为我会将它发布给其他需要的人做同样的事情。

                private void test()
                {
                    // table has a field Description of type varchar(200)
                    WDMDBEntities context = new WDMDBEntities();
                    var query = context.Brands;
                    List<Brand> records = query.ToList();
                    if (records.Count > 0)
                    {
                        Brand currentRecord = records[0];
                        currentRecord.Description = "some new text";
                        string originalValue = null;
                        switch (context.Entry(currentRecord).State)
                        {
                            case System.Data.Entity.EntityState.Added:
                                originalValue = null;
                                break;
                            case System.Data.Entity.EntityState.Deleted:
                            case System.Data.Entity.EntityState.Detached:
                            case System.Data.Entity.EntityState.Modified:
                            case System.Data.Entity.EntityState.Unchanged:
                                originalValue = context.Entry(currentRecord).Property(u => u.Description).OriginalValue;
                                break;
                        }
                    }
                    context.Dispose();
                }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-04-25
              • 2014-04-14
              • 2020-06-29
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多