asp.net - 使用 Entity Framework 创建具有多个查询的 MVC ViewModel

标签 asp.net asp.net-mvc entity-framework

我是 MVC 的新手,正在尝试探索更多 ViewModels。我有一个产品类别页面,我想显示产品类别以及产品及其相关图像。我将简化其中一些表,只关注将这些数据返回到 View 的逻辑。我的 View 与填充的下拉列表一起使用,但我不确定如何在 CategoryViewModel 中填充 ProductViewModel。

数据库

分类表

CategoryId
CategoryName
CategoryDescription

产品表

ProductId
ProductName
ProductDescription
ProductPrice
CategoryId

产品图片表

ProductId
ProductImage1
ProductImage2
ProductImage3
ProductImage4
ProductImage5
ProductImage6
ProductImage7
ProductImage8
ProductImage9
ProductImage10

View 模型

public class ProductViewModel
{
  public Product ProductVM { get; set; }
  public ProductImage ProductImageVM { get; set; }
}

public class CategoryViewModel
{
  public List<Category> Category { get; set; }
  public List<ProductViewModel> Products { set;get;} 
}

Controller

public ActionResult Index()
{
    var model = new CategoryViewModel();
    model.Category = db.Categories.OrderBy(d => d.CategoryName).ToList();
    model.Products = from p in db.Products
                             join pi in db.ProductImages on p.ProductId equals pi.ProductId
                             orderby p.ProductPrice descending

    return View(model);
}

查看

@model CategoryViewModel

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

<table>
@foreach (var product in Model.Products)
    {
        <tr>
            <td>@item.ProductImage.ProductImage1</td>
            <td>@item.Product.ProductName</td>
            <td>@item.Product.ProductPrice</td>
            <td>@item.Product.ProductDescription</td>
        </tr>
    }
</table

最佳答案

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

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

然后,在该文件夹中创建一个“服务”类。例如,我将创建一个名为 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
        });
    }
}

现在,您可以轻松地从 Controller 中检索 ViewModel:

public ActionResult Index()
{
    CategoryService service = new CategoryService();
    return View(service.GetCategoryViewModel());
}

在您的 View 中,您必须更新模型引用以处理 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

这应该为您指明了您需要前进的总体方向。如果您对以上任何内容有疑问,请随时发表评论,我会尽力澄清。

编辑: 此外,我建议进一步分解服务类中的功能。我在这里避免了这一点,因为我不想为您提供 10+ 函数类。

编辑2: 更新了 GetProductViewModel() 函数。由于 Product 和 ProductImage 模型之间存在一对一的关系,并且 ProductImage 在 ProductId 上有一个引用 Product 的 ProductId 的外键,因此 ProductImage 应该作为 Product 模型上的子实体可用。

因此,您可以使用方便的 lambda 表达式在一次数据库访问中生成 ProductViewModel 列表。我已经使用此 lambda 表达式生成了许多列表,但您可能需要对其进行修改才能正常工作。

关于asp.net - 使用 Entity Framework 创建具有多个查询的 MVC ViewModel,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53089808/

相关文章:

asp.net mvc 5 捆绑 jquery 不工作

asp.net-mvc - 从 Javascript 更新 Razor 模型

c# - 如何将模型中的列表作为 ajax 调用的参数传递?

c# - 如何在 c#.net Web 应用程序中读取 pdf 文件中的文本

c# - 404 在 C# WebApi 上找不到

C# 应用程序和 asp.NET session

c# - 在类构造函数中将 icollection 设置为列表时,如何通过索引从 icollection 中获取项目?

c# - 使用 Entity Framework 更新外键

c# - 服务和存储库 -> 帮助我不要重复代码

c# - 具有动态 Entity.Property 唯一检查的通用 ValidationAttribute(在运行时设置)