C# 更新实体框架中从缓存返回的实体

C# 更新实体框架中从缓存返回的实体,c#,.net,entity-framework,caching,C#,.net,Entity Framework,Caching,我有两个用于数据处理的存储库(Cache,EntityFramework)。我想从缓存中获取实体并在实体框架中更新,例如错误代码: User user = _cacheRepo.Get<User>(2); user.Name = "Qolzam"; _entityFrameworkRpo.Update<User>(user); User User=\u cacheRepo.Get(2); user.Name=“Qolzam”; _entityFrameworkRpo.U

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

User user = _cacheRepo.Get<User>(2);
user.Name = "Qolzam";
_entityFrameworkRpo.Update<User>(user);
User User=\u cacheRepo.Get(2);
user.Name=“Qolzam”;
_entityFrameworkRpo.Update(用户);
厄洛尔

无法将实体附加到更新

但在另一方面,该代码起作用:

User user = _entityFrameworkRpo.Get<User>(2);
user.Name = "Qolzam";
_entityFrameworkRpo.Update<User>(user);
User User=\u entityFrameworkRpo.Get(2);
user.Name=“Qolzam”;
_entityFrameworkRpo.Update(用户);
成功:将实体附加到更新是否正常

[更新]

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;
  }
public T Update(T项,bool commit=true),其中T:class,IBaseEntity
{
var分录=该分录(项目);
if(条目!=null)
{
entry.State=EntityState.Modified;
条目.CurrentValues.SetValues(项目);
}
其他的
{
本.附(项);
}
这是SaveChanges();
退货项目;
}
[例外]

捕获到System.InvalidOperationException _HResult=-2146233079 _message=附加“Domain.User”类型的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。 HResult=-2146233079 IsTransient=false Message=附加“Domain.User”类型的实体失败,因为相同类型的另一个实体已具有相同的主键值。如果图形中的任何实体具有冲突的键值,则在使用“Attach”方法或将实体状态设置为“Unchanged”或“Modified”时可能会发生这种情况。这可能是因为某些实体是新的,尚未收到数据库生成的键值。在这种情况下,使用“添加”方法或“添加”实体状态跟踪图形,然后根据需要将非新实体的状态设置为“未更改”或“已修改”。 Source=EntityFramework 堆栈跟踪: 位于System.Data.Entity.Core.Objects.ObjectContext.VerifyRootForAdd(布尔doAttach、字符串entitySetName、EntityWrapper wrappedEntity、EntityEntry existingEntry、EntitySet和EntitySet、布尔和isNoOperation) 位于System.Data.Entity.Core.Objects.ObjectContext.AttachTo(字符串entitySetName,对象实体) 在System.Data.Entity.Internal.Linq.InternalSet
1.c__DisplayClassa.b_u 9()
位于System.Data.Entity.Internal.Linq.InternalSet
1.ActOnSet(操作操作、EntityState新闻状态、对象实体、字符串方法名) 位于System.Data.Entity.Internal.Linq.InternalSet
1.Attach(对象实体)
位于System.Data.Entity.Internal.InternalEntityEntry.set_State(EntityState值)

在System.Data.Entity.Infrastructure.DbEntityEntry中设置状态(EntityState值)

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

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;
}
protectedoverride void PersistUpdateInternal(IStoreObject storeObject)
{
if(storeObject==null)
抛出新的NullReferenceException(“storeObject”);
var original=GetOriginalEntity(storeObject);
如果(原始!=null)
{
var entry=_context.entry(原始);
entry.CurrentValues.SetValues(storeObject);
}
其他的
{
GetDbSet().Attach((T)storeObject);
_context.Entry(storeObject.State=EntityState.Modified;
}
}
受保护的T GetOriginalEntity(IStoreObject storeObject)
{
var objectContext=((IObjectContextAdapter)_context).objectContext;
var objectSet=objectContext.CreateObjectSet();
var entitySet=objectSet.entitySet;
var keyMembers=entitySet.ElementType.keyMembers;
表达式谓词=i=>true;
foreach(键成员中的var键成员)
{
var-propertyInfo=typeof(T).GetProperty(keyMember.Name);
var pe=表达式参数(类型(T),“i”);
var left=Expression.PropertyOrField(pe,keyMember.Name);
var right=Expression.Constant(propertyInfo.GetValue(storeObject),propertyInfo.PropertyType);
var body=表达式.Equal(左、右);
var whereExpression=Expression.Lambda(body,pe);
谓词=谓词和(whereExpression);
}
var original=GetDbSet().Local.FirstOrDefault(predicate.Compile());
归还原件;
}

你的
\u cacheRepo.Get
\u entityFrameworkRpo.Update
是什么样子?@SergeyBerezovskiy\u cacheRepo.Get()是简单的从RuntimeCache按id获取对象`如果不存在,id从entityframework获取并插入到缓存,entityframework更新是简单的更新使用通用存储库IIRC,不能在存储库之间共享实体。在“eFrapo”中更新“user”之前,请尝试将“user”与“cacheRepo”分离。您可能会在上看到我的答案。