【问题标题】:How do I manually populate ViewModel (Not using AutoMapper!)如何手动填充 ViewModel(不使用 AutoMapper!)
【发布时间】:2012-06-05 23:03:00
【问题描述】:

我知道有很多关于这个主题的帖子,但我找不到可以帮助我做我想做的事的帖子。我知道我最终会使用 Automapper,但在开始使用它之前,我想学习如何手动操作。我想创建一个 ViewModel,通过存储库使用我的实体中的值填充它,并将其发送到我的视图。听起来很简单,我正在努力完成它。我正在使用 MVC 3、EF 4.3、数据库优先。我已经自动生成了我的课程。我正在发布相关实体(为这篇文章缩写/重命名)和类,这是我到目前为止所拥有的:

聚合实体:运输标头

using System;
using System.Collections.Generic;

namespace My.Models
{
public partial class ShippingHdr
{
    public ShippingHdr()
    {
        this.ShippingLI = new HashSet<ShippingLI>();
    }

    public int ID { get; set; }
    public int ShipToSiteID { get; set; }
    public Nullable<System.DateTime> DateShipped { get; set; }
    public Nullable<System.DateTime> EstDeliveryDate { get; set; }
    public string FromSitePOC { get; set; }
    public Nullable<int> ShipperID { get; set; }
    public string TrackingNo { get; set; }
    public string Comments { get; set;}
    public virtual Shippers Shippers { get; set; }
    public virtual ICollection<ShippingLI> ShippingLI { get; set; }
}

}

这是我的视图模型

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace My.Models.ViewModels
{

public class ShippingHeaderSummaryVM
{
    public int ID { get; set; }
    public string Site { get; set; }
    public Nullable<System.DateTime> DateShipped { get; set; }
    public Nullable<System.DateTime> EstDeliveryDate { get; set; }
    public string TrackingNo { get; set; }
    public string HeaderComments { get; set; }
    public string Shipper { get; set; }
    public int NumOrders { get; set; }
    public string Site { get; set; }


}

}

这是一个查询,我必须返回我想用来填充我的 Viewmodel 的项目。我相信最好的地方是在存储库中。我验证了它使用 LinqPad 返回了我想要的数据(因此缺少对我的 dbContxt 的引用)。我只是不知道如何从查询中获取值到 ViewModel:

var shipments = from h in c.ShippingHdrs
                        where (h.ShippingLI.Count > 1)
                        join
                        e in c.vHr_Employees on h.CreatedBy equals e.ID
                        join
                        s in c.Shippers on h.ShipperID equals s.ShipperID
                        join
                        r in vAaiomsSites on h.ShipToSiteID equals r.SiteID

                        select new
                        {
                            h.ID,
                            r.Site,
                            h.EstDeliveryDate,
                            h.DateShipped,
                            h.TrackingNumber,
                            h.HeaderComments,
                            e.LastName,
                            h.ShippingLI.Count,
                            s.Shipper
                                                        };

所以我想要做的,同样不使用 Automapper,是用 ShippingHdr 实体中的所有行填充 ViewModel 并将其传递给我的视图。

这里是需要映射的文件:

从货件映射的ShippingHeaderSummaryVM

ID = h.ID
Site = r.Site
DateShipped = h.DateShipped
EstDeliveryDate = h.EstDeliveryDate
TrackingNo = h.TrackingNumber
FromSitePOC = e.LastName
NumOrders = h.ShippingLI.Count
Shipper = s.Shipper
HeaderComments = h.HeaderComments

我被困在这里。 如何从查询中填充 ViewModel? 那么我如何从我的控制器调用该操作?

我希望我已经提供了足够的信息,任何帮助将不胜感激。

【问题讨论】:

  • 提示,你可以直接使用Nullable&lt;System.DateTime&gt;,而不是DateTime?
  • 你应该可以说select new ShippingHeaderSummaryVM {},这是你的输出而不是使用模型绑定器作为输入?
  • @Lavinski,我刚刚为这篇文章复制/粘贴了我生成的实体,我真的不明白为什么有些地方是用 Nullable 生成的,而另一些不是。我认为它会与我的 SQL 表匹配,但它没有。
  • 啊,我没有意识到它是生成的,我习惯了先编码。

标签: asp.net-mvc


【解决方案1】:

为了根据您的视图模型对象填充发货列表,您需要创建一个映射方法,以从数据库中的发货集合映射到基于您的视图模型的发货集合:

var model = new List<ShippingHeaderSummaryVM>();

foreach(var h in shipments)
{

    var viewModel = new ShippingHeaderSummaryVM
    {
    ID = h.ID
    Site = r.Site
    DateShipped = h.DateShipped
    EstDeliveryDate = h.EstDeliveryDate
    TrackingNo = h.TrackingNumber
    FromSitePOC = e.LastName
    NumOrders = h.ShippingLI.Count
    Shipper = s.Shipper
    HeaderComments = h.HeaderComments
    }

    model.Add(viewModel);
}

return model;

附带说明一下,在您启动并运行 AutoMapper 后,这将变成一条线:

var model = Mapper.Map<IEnumerable<ShippingHdr>, IEnumerable<ShippingHeaderSummaryVM>>(shipments);

同时,学习如何手动操作也很棒。手动映射模型不会以任何方式或形式真正使您受益。使用 AutoMapper。

【讨论】:

  • 我确实打算使用 Automapper,我只是觉得我需要先真正了解机制。迫不及待想试试这个。谢谢
  • 当你说手动映射没有任何好处时,我读过一篇文章 [link]devtrends.co.uk/blog/… 说通过使用 Automapper,在映射发生之前读取整个模型。除了使用他构建的插件之外,如果出现性能问题,这似乎是手动映射的潜在原因。我的应用程序的用户正在使用基于卫星的 Internet 服务,延迟是一个杀手,我希望尽可能减少数据库访问。 Automapper 不会带来比我需要的更多的东西吗?
  • automapper 使用的“映射”本身通常在 Global.asax 方法的 OnApplicationStarted 部分中创建。在此配置中,您可以告诉自动映射器您希望从域实体到视图模型的字段。根据我的经验,automapper 的性能与手动映射的性能没有任何不同,我发现我的代码更清晰且更易于遵循。 IMO automapper 带来的好处是非常非常非常微不足道的影响(如果有的话)。您还可以对映射进行单元测试!
  • 谢谢,我已经厌倦了手动映射,我只做了这个视图模型。单元测试,我听说过;)
  • 或在使用 AutoMap 属性对您的映射进行 AoP 时方法中的零行 :)
【解决方案2】:

你也可以使用 Linq 来做这样的事情......

shipments.Select(h => new ShippingHeaderSummaryVM(){
    ID = h.ID,
    Site = r.Site,
    DateShipped = h.DateShipped,
    EstDeliveryDate = h.EstDeliveryDate,
    TrackingNo = h.TrackingNumber,
    FromSitePOC = e.LastName,
    NumOrders = h.ShippingLI.Count,
    Shipper = s.Shipper,
    HeaderComments = h.HeaderComments
});

请注意,虽然映射视图模型非常适合传递给视图,但在从视图模型读取以更新数据库时,请务必手动执行。

编辑:感谢您的错字更正:-)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    • 1970-01-01
    • 1970-01-01
    • 2016-02-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多