2013-11-15 2 views
6

я задал вопрос о ASP.NET MVC Generic Controller и this answer показывает контроллер, как это:Как использовать ASP.NET MVC Generic Controller для заполнения правильной модели

public abstract class GenericController<T> 
    where T : class 
{ 
    public virtual ActionResult Details(int id) 
    { 
     var model = _repository.Set<T>().Find(id); 
     return View(model); 
    } 
} 

который может быть реализован, как это ,

public class FooController : GenericController<Foo> 
{ 

} 

Теперь, когда кто-то просит/Foo/Детали/42, то entitiy вытягивается из _repository-х Set<Foo>(), не имея ничего писать для этого в FooController.

, как он объясняет, что это хорошо, но думаю, что я хочу, чтобы разработать универсальный контроллер для продукта и клиента, где я не буду использовать EF, чтобы загрузить продукт & модель клиента достаточно использовать блок приложения для доступа к данным MS.

public abstract class GenericController<T> 
     where T : class 
    { 
     public virtual ActionResult Details(int id) 
     { 
      //var model = _repository.Set<T>().Find(id); 
      var model =customer.load(id); 
      or 
      var model =product.load(id); 
      return View(model); 
     } 
    } 

Так что, когда приходит запрос как /Customer/Details/42 or /product/Details/11 затем подробно метод родового контроллера будет вызывать, но как мы можем обнаружить, что запрос исходит от того, какого контроллера и, соответственно, создать экземпляр класса правильно загрузить подходящую модель.

Если запрос приходит для Клиента, тогда мне нужно загрузить данные клиента из метода подробных действий или если запрос поступит на продукт, тогда мне нужно загрузить информацию о продукте из метода действия детали общего контроллера.

Как использовать обобщения для получения набора данных типа T с блоком данных Entity Framework?

+0

Какова цель универсального контроллера? –

+0

Вам нужно будет показать код, в котором вы инициализируете блок данных в контроллере, который в настоящее время работает. Дело в том, что вы не можете получить модель по типу; вы можете вернуть свой репозиторий. Вот что вы можете использовать метод Entity Frameworks 'DbContext.Set ()', поэтому ваш универсальный контроллер _doesn't_ знает во время компиляции, какую конкретную модель он вернет. Мы можем показать пример для блока данных, но это делается проще всего, если вы покажете свой текущий код. – CodeCaster

ответ

12

Вы можете создать набор хранилищ для работы с лицами, как CustomerRepository, ProductRepository от базового интерфейса как

public interface IBaseRepository 
{ 
    T Get<T>(int id); 
    void Save<T>(T entity); 
} 

, а затем расширить базовый класс контроллера с типом хранилища и его экземпляр с любой из рамок DI

public abstract class GenericController<T, TRepo> 
     where T : class 
     where TRepo : IBaseRepository, new() 
    { 
     private IBaseRepository repository; 

     public GenericController() 
     { 
      repository = new TRepo(); 
     } 

     public virtual ActionResult Details(int id) 
     { 
      var model =repository.Get<T>(id); 
      return View(model); 
     } 
    } 

Пример CustomerController

public class CustomerController : GenericController<Customer, CustomerRepository> 
{ 

} 

где CustomerRepository:

public class CustomerRepository : IBaseRepository 
{ 
    public T Get <T>(int id) 
    { 
    // load data from DB 
    return new Customer(); 
    } 
} 
+0

спасибо за ответ, но вы можете дать мне полный код для продукта и клиента .... но я хотел бы упомянуть, что я не буду использовать EF, а я бы использовал ado.net для взаимодействия с db. спасибо – Mou

+0

Не имеет значения, как вы реализуете реализацию IBaseRepository. Главным пунктом являются контроллеры продуктов и клиентов, определенные с конкретным типом объекта и типом репозитория. Например, если у вас есть CustomerRepository: IBaseRepository для вашего объекта Customer, вы должны иметь только открытый класс CustomerContoller: GenericController {} определение для класса контроллера. –

+0

Какова основная цель универсального контроллера ....... какое преимущество мы получаем от этого .... пожалуйста, объясните, если это возможно. –

7

Я не думаю, что разумно размещать данные и бизнес-логику, подобные этим в контроллерах, когда размер и сложность вашего приложения превышают определенный момент. Вы должны создавать репозитории, которые обрабатывают доступ к данным и абстрагируют технологию (EF, plain ADO.NET и т. Д.) От потребителей. Вы можете использовать эти репозитории в своем контроллере, но это будет означать, что ваши контроллеры по-прежнему содержат бизнес-логику, которую вы не хотите. Контроллеры должны быть тонкими.

Что я сделал, это создать сервисный уровень между моими репозиториями и контроллерами, которые содержат бизнес-логику и делегируют доступ к данным в репозитории. Я использую эти службы в своих контроллерах для извлечения моих моделей домена, где я сопоставляю их для просмотра моделей. Вам нужно, чтобы контейнер Inversion of Control «склеил» слои вместе и обеспечил свободную связь между ними.

Поиск репозитория 'C# mvc и шаблона обслуживания' приведет к множеству примеров. Я нашел this post хороший, за исключением того факта, что он возвращает модели просмотра из своих услуг, а не моделей домена.

Это всего лишь мои 2 цента, пожалуйста, имейте в виду, что все вышеперечисленное учитывается только тогда, когда у вас есть приложение «среднего радиуса действия», а не типичный веб-сайт для обучения/тестирования.

+0

Хенку вы слушаете, хммм! –

+0

Это хорошая идея, но мои знания не очень хороши в отношении создания репозиториев, но хотелось бы знать, как я могу сообщить свои репозитории, чтобы загружать данные о клиентах, когда люди запрашивают этот URL/Customer/Details/42? или загружать данные о продукте, когда/product/Details/11. Могу ли посоветовать. Могу ли вы дать мне любую статью для моего сценария. спасибо – Mou

+0

@ Можете проверить URL, который я упомянул в своем ответе, он дает подробный пример. –

3

Учитывая мои заявления об отказе в другом вопросе, и мои комментарии здесь объяснить, почему это не окончательное решение, я постараюсь дать более конкретную реализацию:

public abstract class GenericController<T> : Controller 
    where T : class 
{ 
    protected YourEFContext _dataSource; 

    public GenericController() 
    { 
     _dataSource = new YourEFContext(); 
    } 

    public virtual ActionResult Details(int id) 
    { 
     var model = _dataSource.Set<T>().Find(id); 
     return View(model); 
    } 
} 

public class CustomerController : GenericController<Customer> 
{ 

} 

Это всего код, который необходим для того, чтобы /Customers/Details/42 загрузил пользователя с ID 42, загруженным из контекста инфраструктуры Entity Framework. «Общая» часть решается методом Entity Framework DbContext.Set<T>(), который возвращает DbSet<TEntity> для соответствующего объекта, в данном случае DbSet<Customer>, который вы можете запросить.

Это, как говорится, есть много проблем с фактически используя этот код:

  • Вы не хотите, чтобы ваш контроллер знать о вашем доступе к данным. Как вы видите, в контроллере используется свойство YourEFContext, тесно связанное с Entity Framework. Вы захотите отвлечь это в шаблоне репозитория.
  • Вы не хотите, чтобы ваш контроллер создал экземпляр, его данные должны быть введены.
  • Вы не хотите, чтобы ваш контроллер возвращал объекты сущности. Вы ищете ViewModels и Mapper.
  • Вы не хотите, чтобы ваш контроллер сделал доступ к данным. Переместите доступ к данным на уровне обслуживания, который также содержит вашу бизнес-логику, снова отрисуйте его с помощью шаблона репозитория.

Теперь ваш вопрос на самом деле «ли Enterprise Library блок данных есть метод, как GetDataSet<T>», так что вы не должны обращаться к customer и product в вашем родовом контроллере, но, к сожалению, я могу Не находите это, поскольку я не использовал EntLib в течение нескольких лет. Это поможет, если вы покажете код, который вы используете в настоящее время для доступа к вашей базе данных.

Конечная цель, которую вы ищете: только

[  MVC    ] <=> [   Service   ] <=> [ Repository ] 
View ViewModel Controller  BusinessModel BusinessLogic  DataModel Database 

Ваш контроллер общается с вашим услугам, чтобы создать/чтение/обновление/удаление BusinessModels и выполняет преобразование между ViewModels и BusinessModels (в <=>).Служба содержит бизнес-логику и бизнес-модель (DataContacts при использовании WCF) и, в свою очередь, карты (<=>) в DataModels и обратно, а также переговоры с вашим хранилищем для сохранения ваших моделей.

Я понимаю, что это может быть немного сложно понять сразу, и именно поэтому большинство обучающих программ ASP.NET MVC начинаются со всех трех уровней в одном приложении. Взгляните на ProDinner для более правильного подхода.

+0

Какова основная цель универсального контроллера ....... какое преимущество мы получаем от этого .... пожалуйста, объясните, если это возможно. –

Смежные вопросы