【问题标题】:Not able to add second entity to ViewModel with Automapper?无法使用 Automapper 向 ViewModel 添加第二个实体?
【发布时间】:2016-01-15 03:47:03
【问题描述】:

我仍在学习 MVC,最近有人建议我使用 AutoMapper 来映射我的 ViewModel。所以,我开始了一个测试,但我不了解如何映射两个实体,也找不到示例。

我有一个 Person 表和一个 Address 表。我想将两者组合成一个 ViewModel 以传递给我的 View。查看示例,他们总是展示如何映射一个实体而不是两个实体。

在下面的代码中,我可以看到我的 currentPerson 和 currentAddress 对象都使用调试器填充了数据,但是我的 currentMember ViewModel 只有 Person 数据。这是有道理的,因为我只在 Person 上使用 Mapper.Map 但我如何告诉 currentMember 也映射地址?

public ActionResult Edit(int id = 0)
        {
            using (DataContext db = new DataContext())
            {
                Person currentPerson = db.Person.Find(id);
                Address currentAddress = db.Address.Single(a => a.PID == id);

                AutoMapper.Mapper.CreateMap<Person, AdminViewModel>();
                AutoMapper.Mapper.CreateMap<Address, AdminViewModel>();

                MemberViewModel currentMember = AutoMapper.Mapper.Map<AdminViewModel>(currentPerson);

                return View(currentMember);
            }
        }

【问题讨论】:

  • 如何在AdminViewModel 中创建两个属性,然后分别映射它们?
  • 这就是我最初所做的事情,当时有人建议我使用 Automapper 来不必手动映射属性。
  • 是的,老实说,这就是我一直在做的事情。当您单独映射它们时,手动将它们分配给视图模型
  • 人是否有指向地址的导航属性?在通话中加载它们会更有意义。这样,您就可以使用 AutoMapper 进行映射。

标签: c# asp.net-mvc entity-framework


【解决方案1】:

AutoMapper.Map 具有接受源对象和目标对象的重载。因此,您可以使用以下方式来利用它:

创建视图模型

public class PersonViewModel
{
    //your person fields here..
    //create them with the same name as Person 
    //to avoid having to set each field during mapping  
}

public class AddressViewModel
{
    //your address fields here..
}

public class AdminViewModel
{
    public PersonViewModel Person {get; set;}   

    public AddressViewModel Address {get; set;} 
}

创建映射(您应该将所有映射集中在一个类中):

public class EntityToViewModelProfile : Profile
{
    protected override void Configure()
    {
        //Create mappings for Person and Address
        AutoMapper.Mapper.CreateMap<Person, AdminViewModel>();
        AutoMapper.Mapper.CreateMap<Address, AdminViewModel>();


        //Create a map to AdminViewModel for both Person and Address

        Mapper.CreateMap<Models.Person, Models.AdminViewModel>()
            .ForMember(dest => dest.Person, opt => opt.MapFrom(src => src));

        Mapper.CreateMap<Models.Address, Models.AdminViewModel>()
            .ForMember(dest => dest.Address, opt => opt.MapFrom(src => src));
    }
}

Global.asax.cs注册EntityToViewModelProfile

AutoMapper.Mapper.Initialize(x =>
{
    x.AddProfile<EntityToViewModelProfile>();
});

然后,在您的控制器中使用 .Map 的重载

using (DataContext db = new DataContext())
{
    Person currentPerson = db.Person.Find(id);
    Address currentAddress = db.Address.Single(a => a.PID == id);

    var mapPerson = AutoMapper.Mapper.Map<Person, AdminViewModel>(currentPerson);

    var mapPersonAndAddress = AutoMapper.Mapper.Map<Address, AdminViewModel>(currentAddress, mapPerson);

    return View(mapPersonAndAddress);
}

【讨论】:

  • 什么是destination2
  • @jpgrassi,在“创建映射”中,.ForMember 的用途是什么?从示例中,我看到您使用 ForMember 为参数分配两个值(例如:DisplayName = FristName + LastName)。如果我要一对一映射属性,我还需要 .ForMember 吗?
  • @Caverman,是的,你是对的。我有同样的问题。您可能只需要创建两个简单的映射,一个用于人员,另一个用于地址,但我尚未对此进行测试。我只是把它留给你,这样你就可以清楚地了解发生了什么。
【解决方案2】:

来自 Jpgrassi 的回答看起来不错,这是一种非常酷的转换方式。但是,如果您在 DB 或 BL 层(而不是 Controller 本身)中进行转换,则将 Business Objects 转换为 BOViewModel(Person 到 PersonViewModel 等)更可重用。更多时候,您需要一个单独的项目来定义您的 BOViewModels(类似于 MyProject.BO)

我宁愿按照简单直接的方法来创建 AdminViewModel,

var personViewModel = AutoMapper.Mapper.CreateMap<Person, PersonViewModel>();
var addressViewModel = AutoMapper.Mapper.CreateMap<Address, AddressViewModel>();

这些转换对于将 DB 对象转换为 BO 非常有用,这在理想情况下发生在 DB 或 BL 层中。然后将 personViewModel 和 addressViewModel 传递给 Controller 并在控制器中创建 AdminViewModel。

这很简单,而且这种模式可以跨越服务边界或具有多层的应用程序。

【讨论】:

  • 目前我只是想在控制器中执行此操作,但我确实打算在我进一步了解它之后再回来并重构代码。我希望有一个像业务层这样的中心位置,它可以为我完成所有这些工作,因为我可以看到我需要在几个地方创建 MemberViewModel。诸如成员显示、我的帐户部分和管理部分以编辑它们之类的东西。我宁愿在一个地方维护这段代码,而不是在多个控制器中做同样的事情。
  • 听起来不错!尽量重复使用。如果您保持组件简单,这将自动发生。
猜你喜欢
  • 2019-12-03
  • 2021-01-06
  • 1970-01-01
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-08
相关资源
最近更新 更多