Невозможно надежно запросить общий доступ к базе данных EntityFramework - PullRequest
1 голос
/ 04 октября 2011

Я пытаюсь поделиться простым DbContext с 4 DbSets среди нескольких репозиториев, каждый из моих репозиториев наследуется от этого базового класса

 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

1 Ответ

3 голосов
/ 04 октября 2011

Эта проблема возникает из-за того, что вы обрабатываете 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 из своего поля.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...