1

我正在尝试在多个存储库中共享一个带有 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(string name) 的实现更改为以下非性能代码时,它也可以工作

public IOfferResult GetEntityByName(string name)
{
   foreach (OfferResult offer in Context.Offers)
   {
       if (offerName.ToLower() == offer.Name.ToLower())
       {
           return offer;
       }
   }
}

问题:这里发生了什么?

请记住,如果在我运行测试时数据库存在,我根本不会收到错误。

tia, jt

4

1 回答 1

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 规格

不保证任何实例成员都是线程安全的。

您最好static从您的字段中删除关键字。

于 2011-10-04T17:46:49.500 回答