我有两个存储库(Cache
,EntityFramework
)用于数据处理。我想从cache
获取实体并在EntityFramework
中更新,例如错误代码:
User user = _cacheRepo.Get<User>(2);
user.Name = "Qolzam";
_entityFrameworkRpo.Update<User>(user);
ERORR
无法附加实体进行更新
但另一方面,此代码有效:
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 =附加类型&#39; Domain.User&#39;的实体。失败,因为同一类型的另一个实体已具有相同的主键值。使用&#39;附加&#39;方法或将实体的状态设置为“未更改”#39;或者&#39;修改&#39;如果图中的任何实体具有冲突的键值。这可能是因为某些实体是新的并且尚未收到数据库生成的键值。在这种情况下,请使用&#39;添加&#39;方法或“添加”#39;实体状态跟踪图形,然后将非新实体的状态设置为“未更改”。或者&#39;修改&#39;作为适当的。
的HResult = -2146233079
IsTransient = FALSE
消息=附加类型&#39; Domain.User&#39;的实体。失败,因为同一类型的另一个实体已具有相同的主键值。使用&#39;附加&#39;方法或将实体的状态设置为“未更改”#39;或者&#39;修改&#39;如果图中的任何实体具有冲突的键值。这可能是因为某些实体是新的并且尚未收到数据库生成的键值。在这种情况下,请使用&#39;添加&#39;方法或“添加”#39;实体状态跟踪图形,然后将非新实体的状态设置为“未更改”。或者&#39;修改&#39;作为适当的。
来源=的EntityFramework
堆栈跟踪:
at System.Data.Entity.Core.Objects.ObjectContext.VerifyRootForAdd(Boolean doAttach,String entitySetName,IEntityWrapper wrappedEntity,EntityEntry existingEntry,EntitySet&amp; entitySet,Boolean&amp; isNoOperation)
at System.Data.Entity.Core.Objects.ObjectContext.AttachTo(String entitySetName,Object entity)
at System.Data.Entity.Internal.Linq.InternalSet 1.<>c__DisplayClassa.<Attach>b__9()
at System.Data.Entity.Internal.Linq.InternalSet
1.ActOnSet(Action action,EntityState newState,Object entity,String methodName)
在System.Data.Entity.Internal.Linq.InternalSet 1.Attach(Object entity)
at System.Data.Entity.Internal.InternalEntityEntry.set_State(EntityState value)
at System.Data.Entity.Infrastructure.DbEntityEntry
1.set_State(EntityState value)
答案 0 :(得分:0)
我在repository中共享我的更新方法。我认为你可以使用这种方法。
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;
}