Entity framework 4 如何在实体框架中获取实体的原始值?

Entity framework 4 如何在实体框架中获取实体的原始值?,entity-framework-4,entity,Entity Framework 4,Entity,在EF4.0中,如果我理解正确,实体中有两种类型的值:当前值和原始值。 我们可以通过调用ApplyOriginalValues(TEntity)方法设置原始值,但如何获取原始值?您可以通过 @对于EF 5,Eranga答案已过时。出于某些原因,使用以下语句获取原始值时,EF 5无法正常工作: var originalValues=context.Entry(myEntity.originalValues); 我的工作解决方案使用DbSet中的AsNoTracking()方法,如下例所示: va

在EF4.0中,如果我理解正确,实体中有两种类型的值:当前值和原始值。

我们可以通过调用ApplyOriginalValues(TEntity)方法设置原始值,但如何获取原始值?

您可以通过


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

var originalValues=context.Entry(myEntity.originalValues);
我的工作解决方案使用
DbSet
中的
AsNoTracking()
方法,如下例所示:

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

这可以进一步细化为以下内容:

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

在上面的
中,很好,不需要响应。

我遇到了类似的问题,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;
}
公共T克隆(T实体)
其中T:class,new(){
var clone=newt();
var properties=typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.flattHierarchy)
其中(a=>a.CanRead&&
a、 能写&&
a、 GetMethod.IsFinal);
foreach(属性中的var属性){
SetValue(克隆,property.GetValue(实体));
}
返回克隆;
}
然后将克隆与更改的克隆进行比较

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;
}
公共字符串GenerateChangeText(T原始,T当前)
其中T:class,new(){
var properties=typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.flattHierarchy)
.其中(a=>a.CanRead&&
a、 能写&&
a、 GetMethod.IsFinal);
var changes=string.Empty;
foreach(属性中的var属性){
var originalValue=property.GetValue(原始);
var currentValue=property.GetValue(当前);
如果(originalValue==null&¤tValue==null)继续;
if((originalValue!=null&!originalValue.Equals(currentValue))||
(currentValue!=null&!currentValue.Equals(originalValue))){
changes+=$“将{property}从{original???“NULL”}更改为{current???“NULL”}。”;
}
}
回报变化;
}

有几个版本的Entity Framework正在使用中

我自己更喜欢先编写代码,有了这个API,就很容易了

_context.Entry(Entity).Reload();
文件

旧的API在ObjectContext上有一个刷新方法,它在某些用例中会有所帮助

ObjectContext.Refresh(RefreshMode.StoreWins, Entity);

文档

这个答案指的是实体框架6。在EF 6中,有一个原始值和当前值,在查看并没有找到一个好的答案后,我提出了以下测试函数,并认为我会将其发布给其他需要这样做的人

    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();
    }
private void test()
{
//表具有varchar(200)类型的字段说明
WDMDBenties上下文=新的WDMDBenties();
var query=context.Brands;
列表记录=query.ToList();
如果(records.Count>0)
{
品牌currentRecord=记录[0];
currentRecord.Description=“一些新文本”;
字符串originalValue=null;
开关(context.Entry(currentRecord.State)
{
案例System.Data.Entity.EntityState.Add:
originalValue=null;
打破
案例System.Data.Entity.EntityState.Deleted:
案例System.Data.Entity.EntityState.Distached:
案例System.Data.Entity.EntityState.Modified:
案例System.Data.Entity.EntityState.Unchanged:
originalValue=context.Entry(currentRecord).Property(u=>u.Description).originalValue;
打破
}
}
context.Dispose();
}
对不起我的英语。 通过这种方式,您可以以对象实体的形式获取原始实体值,而无需更改编辑值

例如: 如果你想编辑一个人,上面的一行是这样的

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

originalValues是DbDataRecord类型。如何将其转换为实体类型?@Sun它没有实体类型。您需要将值强制转换为适当的类型。例如
var name=(字符串)原始值[“name”]如何仅获取修改后的值???@AwaisMahmood我认为这值得一个单独的问题。@CiganoMorrisonMendez。。请访问此。。我问了这个问题,但没有得到答案。。请注意,AsNoTracking将从DB读取实体。它可能已被并发任务更改,在这种情况下,您可能会继续使用不正确的数据…@0xDEADBEEF。上下文不是线程安全的,对于这种情况,使用事务很重要,但这是另一个主题。
var originalEntity = (EntityType)context.Entry(editEntity).OriginalValues.ToObject();
var originalPerson = (Person)context.Entry(editPerson).OriginalValues.ToObject();