Asp.net 使用实体框架创建具有多个查询的MVC ViewModel

Asp.net 使用实体框架创建具有多个查询的MVC ViewModel,asp.net,asp.net-mvc,entity-framework,Asp.net,Asp.net Mvc,Entity Framework,我对MVC还不太熟悉,并试图对ViewModels进行更多的探索。我有一个产品类别页面,我想显示产品类别以及产品及其相关图像。我将对其中一些表进行简化,并将重点放在将这些数据返回到视图的逻辑上。我的视图使用已填充的dropdownlist,但我不确定如何在CategoryViewModel中填充ProductViewModel @model CategoryViewModel @Html.DropDownListFor(x => x.CategoryId, new SelectList(

我对MVC还不太熟悉,并试图对ViewModels进行更多的探索。我有一个产品类别页面,我想显示产品类别以及产品及其相关图像。我将对其中一些表进行简化,并将重点放在将这些数据返回到视图的逻辑上。我的视图使用已填充的dropdownlist,但我不确定如何在CategoryViewModel中填充ProductViewModel

@model CategoryViewModel

@Html.DropDownListFor(x => x.CategoryId, new SelectList(Model.Category, "CategoryId", "CategoryName"), "View all Categories")

<table>
@foreach (var item in Model.ProductViewModels)
    {
        <tr>
            <td>@item.ProductImage.ProductImage1</td>
            <td>@item.Product.ProductName</td>
            <td>@item.Product.ProductPrice</td>
            <td>@item.Product.ProductDescription</td>
        </tr>
    }
</table
数据库 类别表

CategoryId
CategoryName
CategoryDescription
ProductId
ProductName
ProductDescription
ProductPrice
CategoryId
ProductId
ProductImage1
ProductImage2
ProductImage3
ProductImage4
ProductImage5
ProductImage6
ProductImage7
ProductImage8
ProductImage9
ProductImage10
产品表

CategoryId
CategoryName
CategoryDescription
ProductId
ProductName
ProductDescription
ProductPrice
CategoryId
ProductId
ProductImage1
ProductImage2
ProductImage3
ProductImage4
ProductImage5
ProductImage6
ProductImage7
ProductImage8
ProductImage9
ProductImage10
ProductImage表

CategoryId
CategoryName
CategoryDescription
ProductId
ProductName
ProductDescription
ProductPrice
CategoryId
ProductId
ProductImage1
ProductImage2
ProductImage3
ProductImage4
ProductImage5
ProductImage6
ProductImage7
ProductImage8
ProductImage9
ProductImage10
视图模型 看法
@model CategoryViewModel
@Html.DropDownListFor(x=>x.CategoryId,新选择列表(Model.Category,“CategoryId”,“CategoryName”),“查看所有类别”)
@foreach(模型产品中的var产品)
{
@item.ProductImage.ProductImage1
@item.Product.ProductName
@商品价格
@item.Product.ProductDescription
}

每当我使用ViewModels时,我都会开发一个服务类来填充它。这有助于保持我的控制器干净和逻辑隔离

首先,创建一个名为“Services”的文件夹来包含这些类。如果使用区域,则在项目层次结构中创建与使用该文件夹的控制器相同级别的文件夹

然后,在该文件夹中创建一个“服务”类。例如,我将创建一个名为
CategoryService
的类,因为ViewModel名为
CategoryViewModel

在本课程中,我将使用以下代码初始化ViewModel:

public class CategoryServices
{
    private MyDbContext db = new MyDbContext();

    internal CategoryViewModel GetCategoryViewModel(){
        return new CategoryViewModel(){
            Category = GetCategories(),
            Products = GetProductViewModel()
        };
    }

    internal List<Category> GetCategories(){
        return db.Categories.OrderBy(d => d.CategoryName).ToList();
    }

    internal List<ProductViewModel> GetProductViewModel(){
        return db.Products.Select(x => new ProductViewModel()
        {
            ProductVM = x,
            ProductImageVM = x.ProductImage
        });
    }
}
在视图中,必须更新模型引用以处理ViewModel中的内容

@model CategoryViewModel

@Html.DropDownListFor(x => x.CategoryId, new SelectList(Model.Category, "CategoryId", "CategoryName"), "View all Categories")

<table>
@foreach (var item in Model.ProductViewModels)
    {
        <tr>
            <td>@item.ProductImage.ProductImage1</td>
            <td>@item.Product.ProductName</td>
            <td>@item.Product.ProductPrice</td>
            <td>@item.Product.ProductDescription</td>
        </tr>
    }
</table
@model CategoryViewModel
@Html.DropDownListFor(x=>x.CategoryId,新选择列表(Model.Category,“CategoryId”,“CategoryName”),“查看所有类别”)
@foreach(Model.ProductViewModels中的var项)
{
@item.ProductImage.ProductImage1
@item.Product.ProductName
@商品价格
@item.Product.ProductDescription
}

我对杰克采取了类似的方法,只是我把它进一步分开了

看起来有些过分了(在某些情况下可能是这样),但这会让你在未来的道路上有更多的灵活性

我将创建两个类:

  • ProductViewModelFactory
    (创建一个
    ProductViewModel
  • CategoryViewModelFactory
    (创建一个
    CategoryVieWModel
ProductViewModelFactory
可以在内部使用任意数量的存储库、服务或其他必要的视图模型工厂来构建其数据

在这种情况下,
ProductViewModelFactory
将在内部调用
CategoryViewModelFactory
以创建
CategoryViewModel
ProductViewModelFactory
也可能调用
ProductRepository
ProductService
并将从某种持久存储中检索到的返回的
产品
映射到视图模型

它可能还会调用其他一些东西——如果现在不调用,很有可能在以后添加更多功能时调用

CategoryViewModelFactory
可能会调用
CategoryService
CategoryRepository
,并将该数据映射到
CategoryViewModel

那么,这些额外的层给我们带来了什么好处呢?毕竟,这需要更多的工作

当然,有YAGNI,但根据我的经验,这种方法提供了最大的灵活性,以最少的工作量处理意外需求

当你想到雅格尼,但你刚刚发现你真的需要它时,可能会导致一些灾难性的情况——因此,我认为,值得额外投入20%的精力来创建一个简单一致的结构,在大多数情况下确保你不会把自己画进一个角落

  • ViewModelFactorys与实际检索数据的存储库或服务完全分离。
  • 这意味着,当需要一个完全不同的视图时,您不会在您的服务或存储库中乱搞——它们应该返回尽可能原始的数据

    他们还可以调用其他ViewModelFactory,这变得很方便,因为随着应用程序的增长,您需要在ViewModel中包含其他ViewModel,在ViewModel中包含ViewModel,在ViewModel中包含ViewModel。。。你明白了

  • 当您需要测试某些东西,或者出于任何原因无法使用实际实现时,模拟一个假的ViewModelFactory、存储库或服务并使用依赖项注入将变得非常简单。
  • 在以下情况下,这种情况比您想象的要多: -在某些情况下有一个bug需要测试, -另一个从属组件未完成, -您需要为前端开发的视图返回一组特定的数据, -要创建一系列测试, -您需要返回客户端演示等的特定数据

  • 使用应用程序中的任何类都变得简单,因为所有内容都是一个黑盒子。
  • 您不必关心视图模型工厂、服务或存储库如何获取或返回数据。你不必关心在你当前学习的课程之外有什么东西在消耗它

    如果您需要一块数据,您只需根据需要注入它的视图模型工厂、服务或存储库,传递一些参数,然后在整个应用程序中以可预测、一致的模式工作

    总结一下,以下是大致的生命周期:

  • 客户端向控制器操作发出请求
  • 控制器操作调用单个视图模型工厂以获取操作视图的数据
  • 视图模型工厂调用任意数量的其他服务、存储库或其他视图模型工厂(它们