简体   繁体   English

使用AutoMapper将DTO映射回模型

[英]Mapping DTO back to model with AutoMapper

I have a Fixture model : 我有一个Fixture模型:

public partial class Fixture
{
    public int FixtureId { get; set; }
    public string Season { get; set; }
    public byte Week { get; set; }

    //foreign key
    public int AwayTeamId { get; set; }
    //navigation properties
    public virtual Team AwayTeam { get; set; }

    //foreign key
    public int HomeTeamId { get; set; }
    //navigation properties
    public virtual Team HomeTeam { get; set; }

    public byte? AwayTeamScore { get; set; }
    public byte? HomeTeamScore { get; set; }
}

And a Fixture DTO : 还有一个夹具DTO:

public class FixtureDTO
{
    public int Id { get; set; }
    public string Season { get; set; }
    public byte Week { get; set; }
    public string AwayTeamName { get; set; }
    public string HomeTeamName { get; set; }
    public byte? AwayTeamScore { get; set; }
    public byte? HomeTeamScore { get; set; }
}

I am using AutoMapper for the mapping and this is my first attempt using it. 我正在使用AutoMapper进行映射,这是我第一次尝试使用它。 Here is my mapping : 这是我的映射:

CreateMap<Fixture, FixtureDTO>()
            .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.FixtureId))
            .ForMember(dest => dest.AwayTeamName, opt => opt.MapFrom(src => src.AwayTeam.TeamName))
            .ForMember(dest => dest.HomeTeamName, opt => opt.MapFrom(src => src.HomeTeam.TeamName));
        CreateMap<FixtureDTO, Fixture>();

It works fine in taking the Fixture and mapping it to the FixtureDTO which I use to display the data. 在使用Fixture并将其映射到我用来显示数据的FixtureDTO时,它可以很好地工作。 But when I want to update the data and pass the FixtureDTO back to map it back to Fixture I get an error. 但是,当我想更新数据并将FixtureDTO传递回以将其映射回Fixture时,出现错误。

public HttpResponseMessage PutFixture(int id, FixtureDTO fixture)
    {
        if (ModelState.IsValid && id == fixture.Id)
        {
            //do mapping manually here?

            var updated = _repository.UpdateFixture(Mapper.Map<Fixture>(fixture));
            return Request.CreateResponse(updated ? HttpStatusCode.OK : HttpStatusCode.NotFound);
        }
        return Request.CreateResponse(HttpStatusCode.BadRequest);
    }

This is the error I get : 这是我得到的错误:

Store update, insert, or delete statement affected an unexpected number of rows (0). Entities may have been modified or deleted since entities were loaded. Refresh ObjectStateManager entries.

Can anybody help with this? 有人可以帮忙吗?

EDIT : Reverse mapping : 编辑:反向映射:

CreateMap<Fixture, FixtureDTO>()
            .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.FixtureId))
            .ForMember(dest => dest.AwayTeamName, opt => opt.MapFrom(src => src.AwayTeam.TeamName))
            .ForMember(dest => dest.HomeTeamName, opt => opt.MapFrom(src => src.HomeTeam.TeamName));
        CreateMap<FixtureDTO, Fixture>()
            .ForMember(dest => dest.FixtureId, opt => opt.MapFrom(src => src.Id))
            .ForMember(dest => dest.AwayTeam.TeamName, opt => opt.MapFrom(src => src.AwayTeamName))
            .ForMember(dest => dest.HomeTeam.TeamName, opt => opt.MapFrom(src => src.HomeTeamName));

Generally that exception is thrown by EF when it detects one of the following: 通常,当EF检测到以下情况之一时,就会引发该异常:

Opimistic Concurrency Violation : This usually occurs when the entity you are trying to edit was modified else where during the time you loaded, edited and saved it. 乐观并发冲突 :通常在修改您要编辑的实体时发生,否则会在您加载,编辑和保存该实体的时间进行修改。 (see: Entity Framework: "Store update, insert, or delete statement affected an unexpected number of rows (0)." ) (请参阅: 实体框架:“存储更新,插入或删除语句影响了意外的行数(0)。”

An Incorrectly set ID : No ID set for Pks or FKs. ID设置不正确 :未为Pks或FK 设置ID I've also seen an exception like this when I mistakenly set an Entity's FK to a value and set the associated object to an object with a different ID. 当我错误地将Entity的FK设置为​​值并将关联的对象设置为具有不同ID的对象时,我也看到了这样的异常。

Most likely this exception is being thrown because of some code in your repository. 由于存储库中的某些代码,很可能引发此异常。 If you post the code in your repository we might get a better idea of what is causing the exception. 如果将代码发布到存储库中,我们可能会更好地了解导致异常的原因。

First, you need to create reverse mapping from DTO to entity (provide custom member mappings, if needed): 首先,您需要创建从DTO到实体的反向映射(如果需要,提供自定义成员映射):

Mapper.CreateMap<FixtureDTO, Fixture>();

And second - retrieve, map, and update existing entity 其次-检索,映射和更新现有实体

if (ModelState.IsValid && id == fixture.Id)
{
    Fixture entity = _repository.FindById(fixture.Id);
    Mapper.Map(fixture, entity); // Use this mapping method!
    var updated = _repository.UpdateFixture(entity);
    // etc
} 

Extension to @lazyberezovsky's answer: @lazyberezovsky答案的扩展:

This is an (untested) example of the reverse mapping you might require: 这是您可能需要的反向映射的一个(未经测试的)示例:

CreateMap<FixtureDTO, Fixture>()
        .ForMember(dest => dest.FixtureId,
                   opt => opt.MapFrom(src => src.Id))
        .ForMember(dest => dest.AwayTeam,
                   opt => opt.MapFrom(src => new Team
                                                 {
                                                     TeamName = src.AwayTeamName
                                                 }))
        .ForMember(dest => dest.HomeTeam,
                   opt => opt.MapFrom(src => new Team
                                                 {
                                                     TeamName = src.HomeTeamName
                                                 }));

I've used this format in the past and its worked fine, but alternatively you could also create specific mappings for team. 我过去曾经使用过这种格式,并且效果很好,但也可以为团队创建特定的映射。 Eg: 例如:

CreateMap<string, Team>()....

Also, I presume you are doing it, but assert that your configuration is valid. 另外,我假设您正在执行此操作,但是断言您的配置有效。 Eg: 例如:

[Test]
public void AutoMapper_Configuration_IsValid()
{
    Mapper.Initialize(m => m.AddProfile<MyProfile>());
    Mapper.AssertConfigurationIsValid();
}

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

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