Большая часть моих знаний о ASP.NET MVC 3 основана на чтении книги Адама Фримена и Стивена Сендерсона Pro Framework 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.На нем есть поле выбора, содержащее список доступных TestParent для выбора.Вот как выглядит мой контроллер:
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; }
}
Пожалуйстадайте мне знать, если я забыл включить соответствующий код.Большое спасибо за ваш совет!