使用automapper从ViewModel映射到DTo到域

时间:2012-10-24 14:55:20

标签: asp.net-mvc-3 automapper

我在执行以下映射时遇到了麻烦:

域名(简化版):

public class Ad
{
    // Primary properties
    public int Kms { get; set; }

    // Navigation properties
    public virtual Model Model { get; set; }
}

DTO:

public class CreateAdDto
{
    // Primary properties
    public int Kms { get; set; }

    // Navigation properties
    public virtual ModelDto Model { get; set; }
}

视图模型:

public class CreateAdViewModel
{
    // Primary properties
    public int Kms { get; set; }

    public int Make_Id { get; set; }
    public int Model_Id { get; set; }

    // Navigation properties
    public IEnumerable<SelectListItem> MakeList { get; set; }
    public IEnumerable<SelectListItem> ModelList { get; set; }
}

在Controller中,当我进行映射时,我从视图的下拉列表中丢失了Make_ID:

    public virtual ActionResult Create(CreateAdViewModel adViewModel)
    {
        if (ModelState.IsValid)
        {
            var adDto = Mapper.Map<CreateAdViewModel, CreateAdDto>(adViewModel);

            _adService.CreateAd(adDto);
        }

        return RedirectToAction(MVC.Home.Index());
    }

映射是:

        Mapper.CreateMap<CreateAdViewModel, CreateAdDto>()

感谢。

5 个答案:

答案 0 :(得分:1)

正如您所提到的,广告需要知道Model_Id并将其设置为模型

Mapper.CreateMap<CreateAdDto, Ad>()
         .ForMember(dest => dest.Model, opt => opt.MapFrom(src => new Model { Id = src.Model_Id }));

您还需要从其他映射方面让Dto知道从哪里获取Model id。

Mapper.CreateMap<Ad, CreateAdDto>()
         .ForMember(dest => dest.Model_Id, opt => opt.MapFrom(src => src.Model.Id}));

上面的代码不安全,因为应该添加验证Model是否为null的验证。

对于其余代码,您似乎做得对。包含实体框架的部分要求您附加,因为实体模型已经存在,否则,EF会将此实体插入数据库。

答案 1 :(得分:0)

CreateAdDto没有Make导航属性或Make_Id属性。

答案 2 :(得分:0)

经过一些研究后发现的解决方案:

ViewDomain:

public class CreateAdViewModel
{
    // Primary properties
    public int Kms { get; set; }

    public int Make_Id { get; set; }
    public int Model_Id { get; set; }

    // Navigation properties
    public IEnumerable<SelectListItem> MakeList { get; set; }
    public IEnumerable<SelectListItem> ModelList { get; set; }
}

DTO:

public class CreateAdDto
{
    // Primary properties
    public int Kms { get; set; }
    public int Model_Id { get; set; }

    // Navigation properties
    //public virtual ModelDto Model { get; set; }
}

域:

public class Ad
{
    // Primary properties
    public int Kms { get; set; }

    // Navigation properties
    public virtual Model Model { get; set; }
}

Viewmodel - &gt; Dto Mapping:

        Mapper.CreateMap<CreateAdViewModel, CreateAdDto>();

Dto - &gt;域映射:

        Mapper.CreateMap<CreateAdDto, Ad>()
             .ForMember(dest => dest.Model, opt => opt.MapFrom(src => new Model { Id = src.Model_Id })); 

Atention:

要使用Entity Framework实现此目标,我必须首先将模型实体附加到上下文,然后添加广告新广告:

    public void CreateAd(CreateAdDto adDto)
    {
        var adDomain = Mapper.Map<CreateAdDto, Ad>(adDto);

        _modelRepository.Attach(adDomain.Model);

        _adRepository.Add(adDomain);
        _adRepository.Save();
    }

希望这是最好的做法。

顺便说一下,我想对这个方法有一些看法。

感谢。

答案 3 :(得分:0)

根据我在问题中看到的内容,我建议采用一种简单的方法。您的申请规模中等。我的经验说,你应该非常认真地考虑可维护性。所以试着为自己创建一个简单的应变前进方法,如下面的方法: Application Architecture

我可以详细描述所有图层但是通知你的问题标题我更喜欢只描述模型(bussiness Ojbect)图层:

Model or Business Object layer

好!正如您所见,PM.Model包括: Tow子文件夹包含我们的ViewModel,在库的根目录中,我们有一个.tt文件包含Entity framework Objects(POCO类),我们有一个Mapper文件夹(因为我不喜欢使用autoMapper或像这样的第三方:))。

您可以在域层中看到IListBox接口。我把所有ListBox容器都放到这个接口上。

我希望当前的方法对你有用,但终于我建议删除这个层DTO或ViewModel中的一个,因为将来会非常复杂。

祝你好运

答案 4 :(得分:-1)

你知道这些映射的成本吗?!对于一个简单的插入,你有2层映射(在到达Entity框架之前)。我们可以在不到2层的映射中做更复杂的CRUD。 如何考虑此代码的可维护性?

请保持DRY,KISS,SOLID惯例,并将其作为日常工作的首选。

祝你好运