简体   繁体   English

Entity Framework Core 可以返回视图模型吗

[英]Can Entity Framework Core return view model

I have a situation which can be explained by below analogy.我有一种情况,可以通过以下类比来解释。

Example: let's say we have 3 tables Categories => SubCategories => Products .示例:假设我们有 3 个表Categories => SubCategories => Products

1 category can have many subcategories and 1 subcategory can have many products. 1个类别可以有多个子类别,1个子类别可以有多个产品。

I am showing simple card for products details with category and subcategory names but for it I am writing the EF like.我正在展示带有类别和子类别名称的产品详细信息的简单卡片,但为此我正在编写 EF 之类的内容。

var products = await _context.Products
                             .Where(x => x.IsDeleted == false)
                             .Include(x => x.SubCategory)
                             .Include(x => x.SubCategory.Category).ToListAsync()

The SQL generated is too expensive.生成的 SQL 成本太高。

When the products are reached to the controller then Automapper starts it's magic to map according to my required view model.当产品到达控制器时,Automapper 开始根据我需要的视图模型进行映射。

I am new to Entity Framework Core and I have three questions:我是 Entity Framework Core 的新手,我有三个问题:

  1. Is it there a better way to write above code?有没有更好的方法来编写上面的代码?
  2. Can I return a view model directly from Entity Framework Core?我可以直接从 Entity Framework Core 返回视图模型吗? In the above case, can I return a model with properties showing just names of Products, SubCategory and Category?在上述情况下,我可以返回一个模型,其属性仅显示产品、子类别和类别的名称吗?
  3. If I can't return, then how can I convince myself to stop using Dapper?如果我不能回来,那么我如何说服自己停止使用 Dapper?

Automapper can generate the sql for you, basically doing the mapping to your viewmodel/DTO in the database. Automapper 可以为您生成 sql,基本上是在数据库中映射到您的视图模型/DTO。

Use the ProjectTo extension to IQueryable , explained here .使用IQueryableProjectTo扩展,解释here

  1. Yes.是的。 You can use the ThenInclude operation to make the code easier to read.您可以使用ThenInclude操作使代码更易于阅读。
var products = await _context.Products.Where(x => x.IsDeleted == false)
                                       .Include(x => x.SubCategory)
                                       .ThenInclude(x => x.Category).ToListAsync()
  1. Yes or no.是还是不是。 It depends on what your ViewModel is.这取决于您的ViewModel是什么。

Entity framework is a framework for operating database entities.实体框架是操作数据库实体的框架。 But ViewModel is a concept in MVVM.但是ViewModel是 MVVM 中的一个概念。 It was two different concepts and have no relationship.这是两个不同的概念,没有任何关系。

Usually, the view is rendering what is needed to be rendered.通常,视图正在渲染需要渲染的内容。 So we return it a ViewModel instead of Entity .所以我们返回一个ViewModel而不是Entity If the Entity itself is what you need to be rendered, just return it!如果Entity本身就是你需要渲染的,就返回它! It's ok.没关系。

return View(viewName: "myview", model: products);
@model IEnumerable<Product> // Product is your entity in EF. You can use it in a view.

It's fine.没关系。

But, consider what the view needs is not what you got from entit-framework.但是,请考虑视图需要的不是您从实体框架中获得的。 Now you need to convert the entity to the ViewModel .现在您需要将实体转换为ViewModel For example:例如:

var entity = await dbContext.MyTable.SingleOrDefaultAsync(t => t.Id == id);
var viewModel = new MyViewModel
{
    Color = entity.Color // Only need to return the color, for example.
}
return View(viewModel);
@model MyViewModel

<h2>The color of it is @Model.Color</h2>
@*You can't access other properties of the entity here in the view.*@

And the other properties will not be returned to the view.并且其他属性不会返回到视图。

And some tools like AutoMapper can just help you do the map job. AutoMapper类的一些工具可以帮助您完成地图工作。

Another way is to use Select() to return the column on your choice.另一种方法是使用Select()返回您选择的列。 For example:例如:

Entity definition and view model definition.实体定义和视图模型定义。

public class Product
{
    public int Id { get; set; } // Don't want to return this.
    public string Name { get; set; } // Only want to return this.
}

public class ProductDto
{
    public string Name { get; set; }
}
var products = _context.Products; // While the products is declared, the query was not happened in the database. It only defines an IQueryable object.
List<ProductDto> viewModel = await products.Select(t => new ProductDto
{
    Name = t.Name // Manually map here.
})
.ToListAsync();

return View(viewModel);

In your view:在您看来:

@model List<ProductDto>
foreach (var dto in Model)
{
  <h2>dto.Name</h2>
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM