1

我在 C# 和 Razor 中有一个 ASP.NET MVC3。应用程序的架构分为数据访问层(EF 类 + 存储库)、服务层、控制器、ViewModels 和 View。

我有两个 EF 类Products(key ProdId)和ProductCategories(key ProductCategoryId)。

他们通过一对多的关系ProdCatIdProducts中作为外键ProductCategoryId在类中关联ProductCategories

当然还有一个从类到的导航属性hasCategoryProductsProductCategories

我的存储库类中有该方法:

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

现在我想在我的视图中显示所有带有ProductCategoryName(不是ProdCatId)对应类别的产品。要在我使用的存储库中访问此信息(productDB 是 EF 类):

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

为了在我的视图上获得这些信息,我应该使用我的服务层中的这段代码,或者更糟糕的是我的ViewModel中的代码。但是,通过这种方式,我会在想要保持分离的组件(服务层和 EF 或 ViewModel 和 EF)之间创建耦合。

如果我将这个值从我的存储库(方法string GetProductCategory(int ProdId))获取到我的服务层,连同GetAllProducts().ToList(),我将有两个对象:

1) 一个List<Products>

2) 一个string

如何将这些值传递给我的控制器,然后包装在 ViewModel 中?我应该ProductInfo在包装这些数据的服务层中创建一个类吗?此解决方案创建了ControllerViewModel和类ProductInfo之间的耦合。

不创建耦合的正确做法是什么?

4

2 回答 2

1

两个考虑。1)将代码更改为

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

这样,代码与 EF 无关,它只使用延迟执行……这意味着它可以与支持 Linq 的所有内容(Linq2Sql、EF、NHibernate 等)一起使用

2) 考虑简单地立即隐藏 Product 对象的属性 hasCategory 来解决问题。这意味着不要以懒惰的方式加载它们。仅当您使用在存储库或服务层中管理会话的方法时,这才有意义。如果您有某种按请求会话的方法,那么无论如何都会在需要时填充您的属性 (product.hasCategory.ProductCategoryName)。

于 2012-02-17T10:38:14.403 回答
1

您的 Product 和 ProductCategory 是域模型,而不是视图模型。谷歌视图模型和域模型,以更好地了解它们的不同之处。

如果我是你,我会创建一个名为 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 等工具来避免它。

祝你好运

于 2012-02-18T00:28:42.387 回答