#asp.net-mvc #linq #design-patterns #repository
#asp.net-mvc #linq #шаблоны проектирования #репозиторий
Вопрос:
У меня следующая проблема — или, скорее, срочная потребность в ценном совете — с Microsoft MVC. Определенное действие со стороны клиента приводит к созданию:
- Замечание в таблице Примечания
- Запись в таблице для часовой регистрации
- Запись в журнале изменений для заявок
Я использую сервисный уровень для бизнес-действий и репозитории для действий CRUD. Проблема в том, что мне иногда нужно подключать объекты из разных DataContexts, поэтому я полагаю, что использую некорректный дизайн. Недавно мы начали удалять всю бизнес-логику из наших контроллеров и репозиториев, и это одна из первых вещей, с которыми я сталкиваюсь.
Пример:
BLogic.AddRemarks(Ticket t, ...)
{
Remark r = _remarksRepository.Create();
r.Ticket = t;
_remarksRepository.Add(r);
_remarksRepository.Save();
}
Это запускает kBOOM, поскольку запрос извлекается в контроллере с использованием репозитория. Таким образом, замечание r и запрос t не используют один и тот же контекст данных.
Я могу изменить сигнатуру метода и предоставить int TicketID, но это кажется неправильным. Кроме того, затем я получаю аналогичные проблемы в дальнейшем.
Мои репозитории создаются в конструкторе класса service. Возможно, я должен создать их в начале метода? Даже тогда мне часто приходится передавать идентификаторы вместо истинных объектов.
Ответ №1:
Мое предложение заключается в использовании dependeny injection (или инверсии управления — зависит от того, как бы вы хотели это назвать). Я сам использую castle windor. Действительно простая интеграция с mvc.net . читать дальше
Когда IoC запущен, создайте ContextManager. Что-то вроде этого:
public class ContextManager : IContextManager
{
private XContext context;
public XContext GetContext()
{
return context ?? (context = XContext.Create());
}
}
Задайте IContextManager стиль жизни в соответствии с perwebrequest, и вы получите собственный контекст, к которому сможете получить доступ из репозиториев и служб. и это то же самое для одного запроса.
Редактировать
Вам также необходимо создать свой собственный ControllerFactory
затем вы можете использовать свои сервисы и репозитории следующим образом:
public class MyController : Controller
{
public ISomeService SomeService { get; set; }
public IContextManager ContextManager { get; set; }
...
}
Вам не нужно создавать новые экземпляры для сервисов и репозиториев, и вы можете управлять образом жизни этих объектов из конфигурации. Наиболее разумным было бы singleton
Комментарии:
1. Термины DI и IoC не взаимозаменяемы и означают две разные вещи. Вы достигаете IoC с помощью DI. Windsor, Unity, Ninject — это фреймворки DI, которые вы используете для инвертирования управления. 😉
2. Итак, в начале действия контроллера я должен инициализировать контекстный менеджер и извлечь из него необходимые объекты? Могу ли я получить доступ к context manager с сервисного уровня без явного указания его там? Или это скорее решение на уровне сервиса, поскольку затем я могу создавать репозитории, используя требуемый datacontext.
3. @Paul используйте конструктор контроллера для включения зависимости ContextManager. Проделайте то же самое с классом service layer. Не создавайте экземпляр ContextManager в вашем методе.
4. Спасибо за ваши ответы! В настоящее время я думаю, что наиболее разумным решением действительно является создание datacontext в контроллере. Оттуда я могу инициализировать сервисный уровень. Сервисный уровень может инициализировать репозитории. Таким образом, вся «цепочка» будет использовать один и тот же datacontext.