Шаблон EF и репозитория - в результате получается несколько DbContexts в одном контроллере - любые проблемы (производительность , целостность данных)?

Большая часть моих знаний об ASP.NET MVC 3 пришла из книги Адама Фримена и Стивена Сендерсона Pro ASP.NET MVC 3 Framework. В своем тестовом приложении я старался очень внимательно придерживаться их примеров. Я использую шаблон репозитория плюс Ninject и Moq, что означает, что модульное тестирование работает достаточно хорошо (т.е. без необходимости извлекать данные из базы данных).

В книгах репозитории используются следующим образом:

public class EFDbTestChildRepository
{
    private EFDbContext context = new EFDbContext();

    public IQueryable<TestChild> TestChildren
    {
        get { return context.TestChildren; }
    }

    public void SaveTestChild(TestChild testChild)
    {
        if (testChild.TestChildID == 0)
        {
            context.TestChildren.Add(testChild);
        }
        else
        {
            context.Entry(testChild).State = EntityState.Modified;
        }
        context.SaveChanges();
    }
}

И вот DbContext, который идет с ним:

public class EFDbContext : DbContext
{
    public DbSet<TestParent> TestParents { get; set; }
    public DbSet<TestChild> TestChildren { get; set; }
}

Обратите внимание: для простоты в этом извлеченном примере я оставил здесь интерфейс ITestChildRepository, который Ninject мог бы тогда используйте.

В других источниках я видел более общий подход к репозиторию, когда одного репозитория достаточно для всего приложения. Очевидно, что в моем случае я получаю целый список репозиториев в моем приложении - в основном по одному для каждой сущности в моей модели предметной области. Не уверен в плюсах и минусах этих двух подходов - я просто следил за книгой на всякий случай.

Чтобы наконец перейти к моему вопросу: у каждого репозитория есть свой собственный DbContext - private EFDbContext context = new EFDbContext (); . Рискую ли я получить несколько DbContexts в одном запросе? И приведет ли это к значительным накладным расходам на производительность? Как насчет вероятности конфликтов между контекстами и любых последствий для целостности данных?

Вот пример, когда у меня оказалось более одного репозитория в контроллере.

Две мои таблицы базы данных связаны отношениями внешнего ключа. Мои классы модели предметной области:

public class TestParent
{
    public int TestParentID { get; set; }
    public string Name { get; set; }
    public string Comment { get; set; }

    public virtual ICollection<TestChild> TestChildren { get; set; }
}

public class TestChild
{
    public int TestChildID { get; set; }
    public int TestParentID { get; set; }
    public string Name { get; set; }
    public string Comment { get; set; }

    public virtual TestParent TestParent { get; set; }
}

Веб-приложение содержит страницу, которая позволяет пользователю создать новый TestChild. На нем есть поле выбора, которое содержит список доступных TestParents для выбора. Вот как выглядит мой контроллер:

public class ChildController : Controller
{
    private EFDbTestParentRepository testParentRepository = new EFDbTestParentRepository();
    private EFDbTestChildRepository testChildRepository = new EFDbTestChildRepository();

    public ActionResult List()
    {
        return View(testChildRepository.TestChildren);
    }

    public ViewResult Edit(int testChildID)
    {
        ChildViewModel cvm = new ChildViewModel();
        cvm.TestChild = testChildRepository.TestChildren.First(tc => tc.TestChildID == testChildID);
        cvm.TestParents = testParentRepository.TestParents;
        return View(cvm);
    }

    public ViewResult Create()
    {
        ChildViewModel cvm = new ChildViewModel();
        cvm.TestChild = new TestChild();
        cvm.TestParents = testParentRepository.TestParents;
        return View("Edit", cvm);
    }

    [HttpPost]
    public ActionResult Edit(TestChild testChild)
    {
        try
        {
            if (ModelState.IsValid)
            {
                testChildRepository.SaveTestChild(testChild);
                TempData["message"] = string.Format("Changes to test child have been saved: {0} (ID = {1})",
                                                        testChild.Name,
                                                        testChild.TestChildID);
                return RedirectToAction("List");
            }
        }
        catch (DataException)
        {
            //Log the error (add a variable name after DataException)
            ModelState.AddModelError("", "Unable to save changes. Try again, and if the problem persists see your system administrator.");
        }

        // something wrong with the data values
        return View(testChild);
    }
}

Недостаточно иметь EFDbTestChildRepository, но мне также нужен EFDbTestParentRepository.Оба они присвоены приватным переменным контроллера - и вуаля, мне кажется, что были созданы два DbContexts. Или это неправильно?

Чтобы избежать проблемы, я попытался использовать EFDbTestChildRepository для доступа к TestParents. Но это, очевидно, вызовет только тех, кто уже подключен хотя бы к одному TestChild - так что не то, что я хочу.

Вот код для модели представления:

public class ChildViewModel
{
    public TestChild TestChild { get; set; }
    public IQueryable<TestParent> TestParents { get; set; }
}

Пожалуйста, дайте мне знать, если я забыл включить какой-то соответствующий код. Большое спасибо за ваш совет!

8
задан ralfonso 4 February 2012 в 10:29
поделиться