C# 重新附加分离的实体会引发异常
我正在为我的项目使用EntityFramework6(使用生成的模型和DbContext)。我在程序中使用的体系结构是从应用程序中抽象出数据访问层。这意味着我的实体将大部分处于分离状态 似乎重新连接任何以前连接的实体都是不可能的(或者我做得不好) 我已经单独测试了一个案例,并且能够缩小问题的范围。以下是步骤C# 重新附加分离的实体会引发异常,c#,.net,entity-framework,C#,.net,Entity Framework,我正在为我的项目使用EntityFramework6(使用生成的模型和DbContext)。我在程序中使用的体系结构是从应用程序中抽象出数据访问层。这意味着我的实体将大部分处于分离状态 似乎重新连接任何以前连接的实体都是不可能的(或者我做得不好) 我已经单独测试了一个案例,并且能够缩小问题的范围。以下是步骤 从上下文中获取实体并释放上下文。这将分离实体 public async Task<ArchiveEntry> GetEntry(string api, string id) {
public async Task<ArchiveEntry> GetEntry(string api, string id)
{
// Omitted some code for simplicity
ArchiveEntry entry;
using (var db = new TwinTailDb())
{
entry = await db.ArchiveEntries.Where(a => a.Id == id).SingleOrDefaultAsync();
}
return entry;
}
public async Task RevertChanges()
{
using (var db = new TwinTailDb())
{
if (db.Entry(this).State == EntityState.Detached && Id != 0)
{
db.ArchiveEntries.Attach(this);
//await db.Entry(this).ReloadAsync(); // Commented since this is irrelevant
}
}
}
public async Task Test()
{
ArchiveEntry entry = await ArchiveService.GetEntry(null, "7");
await entry.Save();
await entry.RevertChanges();
}
ChangeTracker
在这些步骤中不包含任何内容。此外,如果我对分离的实体执行任何上下文操作,它会抛出一个异常,表示应该首先附加它。我还注意到内部_entitywrapper仍然有一个对旧上下文的引用
最后,问题来了。如何正确地重新附加实体,以及为什么会发生此异常
我在另一个问题()中问了一些类似的问题,但我觉得我需要发布一个新的问题,因为这是一个更一般的问题
我在程序中使用的体系结构是从应用程序中抽象出数据访问层
看起来您正在ArchiveEntry
类本身上实现这些方法。这不是一个抽象的数据访问层,将实体传递给许多像这样的短期上下文会给您带来麻烦
您不应该给实体类自己的方法来管理持久性问题,而应该将代码放在与实体分开的类中,并确保一旦实体连接到上下文,您就可以继续使用相同的上下文,直到它被释放。一旦上下文被释放,如果您想对实体执行另一个操作,您应该在尝试使用它执行任何(附加的)操作之前从新上下文中检索它
我在程序中使用的体系结构是从应用程序中抽象出数据访问层
看起来您正在ArchiveEntry
类本身上实现这些方法。这不是一个抽象的数据访问层,将实体传递给许多像这样的短期上下文会给您带来麻烦
您不应该给实体类自己的方法来管理持久性问题,而应该将代码放在与实体分开的类中,并确保一旦实体连接到上下文,您就可以继续使用相同的上下文,直到它被释放。一旦上下文被释放,如果您想对实体执行另一个操作,您应该在尝试对其执行任何(附加)操作之前从新上下文中检索它。我使用的是AsNoTracking(),因此,这个异常对我来说很奇怪。下面的代码修复了我代码中的问题。我想我可以在try块中使用代码,并且只使用catch块,但是我从未测试过这个概念
具有PrimaryKey的实体基类
public class EntityBase<K>
{
[NotMapped]
public virtual K PrimaryKey {get;}
}
公共类EntityBase
{
[未映射]
公共虚拟K主密钥{get;}
}
更新功能
public static void Update<T,K>(DbContext context, T t) where T:EntityBase<K>
{
DbSet<T> set = context.Set<T>();
if(set==null) return;
if(context.Entry<T>(t).State == EntityState.Detached)
{
try
{
T attached = set.Attached(t);
context.Entry<T>(attached).State = EntityState.Modified;
}catch(Exception ex)
{
T found = set.Find(t.PrimaryKey);
context.Entry(found).CurrentValues.SetValues(t);
}
}
context.SaveChanges();
}
publicstaticvoidupdate(DbContext-context,T),其中T:EntityBase
{
DbSet set=context.set();
if(set==null)返回;
if(context.Entry(t.State==EntityState.Distached)
{
尝试
{
T附加=设置附加(T);
context.Entry(附件).State=EntityState.Modified;
}捕获(例外情况除外)
{
T found=set.Find(T.PrimaryKey);
context.Entry(find).CurrentValues.SetValues(t);
}
}
SaveChanges();
}
扩展函数
public static void Update<T,K>(this DbContext context, T t) where T:EntityBase<K> => Update<T,K>(context, t);
publicstaticvoidupdate(这个DbContext上下文,T),其中T:EntityBase=>Update(context,T);
我使用的是AsNoTracking(),所以这个异常对我来说很奇怪。下面的代码修复了我代码中的问题。我想我可以在try块中使用代码,并且只使用catch块,但是我从未测试过这个概念
具有PrimaryKey的实体基类
public class EntityBase<K>
{
[NotMapped]
public virtual K PrimaryKey {get;}
}
公共类EntityBase
{
[未映射]
公共虚拟K主密钥{get;}
}
更新功能
public static void Update<T,K>(DbContext context, T t) where T:EntityBase<K>
{
DbSet<T> set = context.Set<T>();
if(set==null) return;
if(context.Entry<T>(t).State == EntityState.Detached)
{
try
{
T attached = set.Attached(t);
context.Entry<T>(attached).State = EntityState.Modified;
}catch(Exception ex)
{
T found = set.Find(t.PrimaryKey);
context.Entry(found).CurrentValues.SetValues(t);
}
}
context.SaveChanges();
}
publicstaticvoidupdate(DbContext-context,T),其中T:EntityBase
{
DbSet set=context.set();
if(set==null)返回;
if(context.Entry(t.State==EntityState.Distached)
{
尝试
{
T附加=设置附加(T);
context.Entry(附件).State=EntityState.Modified;
}捕获(例外情况除外)
{
T found=set.Find(T.PrimaryKey);
context.Entry(find).CurrentValues.SetValues(t);
}
}
SaveChanges();
}
扩展函数
public static void Update<T,K>(this DbContext context, T t) where T:EntityBase<K> => Update<T,K>(context, t);
公共静态无效更新(th