【问题标题】:Update entity in Entity Framework that return from cache更新从缓存返回的实体框架中的实体
【发布时间】:2014-09-12 06:37:17
【问题描述】:

我有两个用于数据处理的存储库(CacheEntityFramework)。我想从cache获取实体并在EntityFramework中更新,例如错误代码:

User user = _cacheRepo.Get<User>(2);
user.Name = "Qolzam";
_entityFrameworkRpo.Update<User>(user);

错误

无法附加要更新的实体

但另一方面,此代码有效:

User user = _entityFrameworkRpo.Get<User>(2);
user.Name = "Qolzam";
_entityFrameworkRpo.Update<User>(user);

成功:将实体附加到更新是可以的

[更新]

public T Update<T>(T item, bool commit = true) where T : class , IBaseEntity
  {
    var entry = this.Entry(item);
    if (entry != null)
    {
       entry.State = EntityState.Modified;
       entry.CurrentValues.SetValues(item);
    }
    else
    {
       this.Attach(item);
    }
    this.SaveChanges();

    return item;
  }

[例外]

System.InvalidOperationException 被捕获 _HResult=-2146233079 _message=附加“Domain.User”类型的实体失败,因为同一类型的另一个实体已经具有相同的主键值。如果图中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新实体,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。 H结果=-2146233079 IsTransient=false Message=附加类型为“Domain.User”的实体失败,因为另一个相同类型的实体已经具有相同的主键值。如果图中的任何实体具有冲突的键值,则在使用“附加”方法或将实体的状态设置为“未更改”或“已修改”时,可能会发生这种情况。这可能是因为某些实体是新实体,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“已添加”实体状态来跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。 来源=实体框架 堆栈跟踪: 在 System.Data.Entity.Core.Objects.ObjectContext.VerifyRootForAdd(布尔 doAttach,字符串 entitySetName,IEntityWrapper WrapperEntity,EntityEntry existingEntry,EntitySet& entitySet,Boolean& isNoOperation) 在 System.Data.Entity.Core.Objects.ObjectContext.AttachTo(字符串 entitySetName,对象实体) 在 System.Data.Entity.Internal.Linq.InternalSet1.<>c__DisplayClassa.<Attach>b__9() at System.Data.Entity.Internal.Linq.InternalSet1.ActOnSet(Action action, EntityState newState, Object entity, String methodName) 在 System.Data.Entity.Internal.Linq.InternalSet1.Attach(Object entity) at System.Data.Entity.Internal.InternalEntityEntry.set_State(EntityState value) at System.Data.Entity.Infrastructure.DbEntityEntry1.set_State(EntityState 值)

【问题讨论】:

标签: c# .net entity-framework caching


【解决方案1】:

我在存储库中分享了我的更新方法。我认为您可以使用此方法。

protected override void PersistUpdateInternal(IStoreObject storeObject)
{
    if (storeObject == null)
        throw new NullReferenceException("storeObject");

    var original = GetOriginalEntity(storeObject);
    if (original != null)
    {
        var entry = _context.Entry(original);
        entry.CurrentValues.SetValues(storeObject);
    }
    else
    {
        GetDbSet().Attach((T)storeObject);
        _context.Entry(storeObject).State = EntityState.Modified;
    }

}
protected T GetOriginalEntity(IStoreObject storeObject)
{
    var objectContext = ((IObjectContextAdapter)_context).ObjectContext;
    var objectSet = objectContext.CreateObjectSet<T>();

    var entitySet = objectSet.EntitySet;
    var keyMembers = entitySet.ElementType.KeyMembers;

    Expression<Func<T, bool>> predicate = i => true;
    foreach (var keyMember in keyMembers)
    {
        var propertyInfo = typeof(T).GetProperty(keyMember.Name);

        var pe = Expression.Parameter(typeof(T), "i");
        var left = Expression.PropertyOrField(pe, keyMember.Name);
        var right = Expression.Constant(propertyInfo.GetValue(storeObject), propertyInfo.PropertyType);
        var body = Expression.Equal(left, right);
        var whereExpression = Expression.Lambda<Func<T, bool>>(body, pe);
        predicate = predicate.And(whereExpression);
    }

    var original = GetDbSet().Local.FirstOrDefault(predicate.Compile());

    return original;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-09
    • 1970-01-01
    • 2012-12-13
    • 2012-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多