В ASP.NET MVC3 как получить данные, относящиеся к связанным таблицам БД, не создавая связи между компонентами? - PullRequest
1 голос
/ 17 февраля 2012

У меня есть ASP.NET MVC3 в C # и Razor.Архитектура приложения разделена на уровень доступа к данным (классы EF + репозиторий), уровень обслуживания, контроллер, ViewModels и View.

У меня есть два класса EF Products (ключ ProdId) и ProductCategories (ключ ProductCategoryId).

Они связаны через отношение один ко многим по ProdCatId в классе Products как внешний ключ и ProductCategoryIdв классе ProductCategories.

Конечно, есть также свойство навигации hasCategory от класса Products до ProductCategories.

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

 public IQueryable<Products> GetAllProducts()
 {
      return productDB.Products;
 }

Теперь я хочу отобразить в своем View все товары с ProductCategoryName (не ProdCatId) их соответствующей категории.Для доступа к этой информации в моем репозитории я использую (productDB - это класс EF):

productDB.Products.Where(n => n.ProdId == prodId)
                  .Select(m => m.hasCategory.ProductCategoryName).First();

Для того, чтобы эта информация была в моем представлении, я должен использовать этот код из моего сервисного уровня или хуже от моего ViewModel .Тем не менее, таким образом, я создаю связь между компонентами, которые я хочу разделить (Service Layer и EF или ViewModel и EF).

Если вместо этого я получу это значение из моего репозитория (метод string GetProductCategory(int ProdId)) в мой СервисСлой вместе с GetAllProducts().ToList(), у меня будет два объекта:

1) A List<Products>

2) A string

Как мне пройти этиЗначения моего контроллера, чтобы затем обернуть в ViewModel?Должен ли я создать класс ProductInfo в моем слое обслуживания, который обернет эти данные?Это решение создает связь между Controller , ViewModel и классом ProductInfo .

Что нужно сделать, чтобы не создать связь?

Ответы [ 2 ]

1 голос
/ 18 февраля 2012

Ваш продукт и категория продукта являются моделями домена, а не моделями просмотра. Google viewmodels и модели доменов, чтобы лучше понять, чем они отличаются.

На вашем месте я бы создал модель представления с именем ProductInfoViewModel. Этот класс будет содержать только ту информацию, которую вы будете отображать о продукте.

public class ProductInfoViewModel
{
   public string Name { get; set; }
   public string Category { get; set; }
}

Теперь у вас есть простой класс, который будет использоваться для отображения некоторых данных.

Да, вы все еще хотите вызвать свой репозиторий или сервисный уровень для получения данных о продукте:

var productDomainModel = productDB.Products.Where(n => n.ProdId == prodId)   
                  .Select(m => m.hasCategory.ProductCategoryName).First();   

Теперь, вместо того, чтобы передавать productDomainModel в ваше представление, вы можете создать модель представления продукта, которая будет легче, поскольку будет содержать только те свойства, которые вы хотите отобразить:

var productViewModel = new ProductViewModel
{
   Name = productDomainModel .Name,
   Category = productDomainModel .Category
}

Теперь вы можете передать эту модель представления вашему представлению:

return View(productViewModel);

Ваше представление теперь знает о модели представления, но оно ничего не знает о вашей модели предметной области, что является хорошей вещью и способствует разделению проблем.

Еще одна вещь, когда мы создаем модель представления продукта из модели предметной области продукта, мы пишем «шаблонный» код, такой как Name = product.Name.

Теперь изображение у вас есть 20 свойств, и вы можете отобразить модель домена, чтобы просмотреть модель несколько раз. Это очень утомительная работа, и вы можете избежать ее, прибегая к помощи инструментов, таких как Automapper.

Удачи

1 голос
/ 17 февраля 2012

Два соображения. 1) изменить код на

repository.GetAllProducts().Products.Where(n => n.ProdId == prodId)
              .Select(m => m.hasCategory.ProductCategoryName).First();

Таким образом, код не зависит от EF и использует только отложенное выполнение ... это означает, что он будет работать со всем, что поддерживает Linq (Linq2Sql, EF, NHibernate и т. Д.)

2) рассмотрите решение проблемы, просто скрыв сразу свойство hasCategory объекта Product. Это значит не загружать их ленивым способом. Это имеет смысл, только если вы используете подход, который управляет сеансом на уровне хранилища или службы. Если у вас есть какой-то подход сессионный для запроса, ваше свойство (product.hasCategory.ProductCategoryName) будет заполнено при необходимости в любом случае.

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