我正在尝试在多个存储库之间共享一个带有4个DbSet的简单DbContext,我的每个存储库都继承自这个基类
public class CodeFirstRepository : IDisposable
{
private static MyContext _ctx = new MyContext();
protected MyContext Context
{
get { return _ctx; }
}
public void Dispose()
{
if (Context != null)
{
Context.Dispose();
}
}
}
问题:这是在资源库之间共享连接的合适方式吗?
访问各种存储库时,我的单元测试中出现间歇性故障。从存储库方法GetEntityByName
抛出异常public IOfferResult GetEntityByName(string name)
{
return Context.Entities.Where(o => o.Name == name).FirstOrDefault()
}
测试方法 Tests.Service.TestDelete 抛出异常:System.ObjectDisposedException:ObjectContext 实例已被处理,不能再用于操作 这需要连接。
如果数据库已存在,则代码按预期执行。当我将GetEntityByName(字符串名称)的实现更改为以下非执行代码时,它也可以工作
public IOfferResult GetEntityByName(string name)
{
foreach (OfferResult offer in Context.Offers)
{
if (offerName.ToLower() == offer.Name.ToLower())
{
return offer;
}
}
}
问题:这里发生了什么?
请记住,如果在运行测试时数据库存在,我根本不会收到错误。
TIA, JT
答案 0 :(得分:3)
出现这个问题是因为你通过将DbContext
声明为一个static
字段来处理CodeFirstRepository
,但是你将它当作一个瞬态实例来处理,只需将它处理掉即可 using (var r = new PersonRepository())
{
// do something
} // When you hit the end of this block, your static DbContext is disposed.
using (var r = new IOfferRepository())
{
r.GetEntityByName("test"); // this will fail because the context is still disposed.
}
的任何实例都会被处置。例如:
DbContext
您应该不以这种方式共享上下文。如果您确实希望所有存储库都使用Context.Dispose()
的单个实例,请删除对DbContext
的调用。这样可以解决您现在遇到的问题,但将来可能会引入其他问题。
但是我强烈建议在多个线程可能尝试同时访问它的情况下使用单个DbContext
。根据{{1}} specs:
不保证所有实例成员都是线程安全的。
最好只从您的字段中删除static
关键字。