我在使用实体框架时遇到了一些奇怪的问题,我不确定这是什么道理。
我应该为每个创建、更新和删除操作使用单独的上下文对象吗?
我有一个实体,它有一个独特的约束。我从不同的线程接收值,并希望将它们存储在实体中并将它们保存到数据库中。如果我正在使用一个 DbContext 并且由于违反唯一约束而添加实体失败,则所有后续存储有效实体的尝试也将失败。这是因为无效实体仍在 DbContext 的集合中。
我认为问题归结为:
/*
* m_context is a memeber variable of the class and created once
* new MyEntity("unique") => creates new entity and sets the unique attribute to the passed value
* the entity's key is set automatically
*/
//works fine
try { m_context.MyEntities.Add(new MyEntity("unique"); m_context.SaveChanges() } catch{}
//fails because of unique constraint violation => this is okay
try { m_context.MyEntities.Add(new MyEntity("unique"); m_context.SaveChanges() } catch{}
//fails, too => not okay and not expected
try { m_context.MyEntities.Add(new MyEntity("unique2"); m_context.SaveChanges() } catch{}
例外是 System.Data.Infrastructure.DbUpdateException(更新条目时发生错误)-> System.Data.UpdateException(更新条目时发生错误)-> System.Data.SQLite.SQLiteException(约束失败列...不是唯一的)
=> 在上面的场景中两次,有单独的上下文(见下文),一次,只有一次。
我认为每个数据库提供程序都会出现问题,并且与 SQLite 无关。
所以至少有两种解决方案:
- 从 MyContext 中的 DbSet 中手动删除第二个实体
- 为每个创建操作使用单独的上下文
我倾向于使用第二种。这是因为我在教程/代码中看到了很多 using 语句。我从来不明白为什么要大规模复制同一个物体,但这可能是一个(那个)原因。这是真的,还是我完全错了。
更新和删除操作也存在此问题。另一个失败的原因可能是外键违规。
那么这里的最佳做法是什么?每个操作单独的上下文对象?但是这个物体真的那么轻吗?我也应该将“每个操作一个上下文”应用于读取操作吗?
如前所述,修复是显而易见的,但我并不完全清楚道德,我对这里的最佳实践很感兴趣。谢谢!