简体   繁体   中英

C# AutoMapper with Entity Framework - Works with List but not single nullable instance

I have a very wierd error that I can't get my head around. I'm using AutoMapper 6 with AutoMapper.Collection and AutoMapper.Collection.EntityFramework .

https://github.com/AutoMapper/AutoMapper.Collection

As you can see from the screenshot below, every component is updated apart from Image that is null for updatedContact . If I however do an explicit mapping for only updatedImage it works. It also works to update a collection of images without a problem. Has anyone experienced this? Other single properties works as well but for some reason Image is causing trouble.

//Works
var updatedArticle = Mapper.Map<ArticleViewModel, Article>(articleVm, articleOriginal);
//Every component is updated a part from Image.
var updatedContact = Mapper.Map<ContactViewModel, Contact>(contactVm, contactOriginal);
//Works
var updatedImage = Mapper.Map<ImageViewModel, Image>(contactVm.Image);
//Works
var newContact = Mapper.Map<ContactViewModel, Contact>(contactVm);

在此处输入图片说明

Mapping:

cfg.CreateMap<ArticleViewModel, Article>(MemberList.Source)
    .EqualityComparison((src, dst) => src.Id == dst.Id);

cfg.CreateMap<ImageViewModel, Image>(MemberList.Source)
    .EqualityComparison((src, dst) => src.Id == dst.Id)
    .ForSourceMember(x => x.IsDeleted, opt => opt.Ignore())
    .ForMember(dest => dest.ImageBytes, opt => opt.MapFrom(src => Encoding.ASCII.GetBytes(src.Image)));

cfg.CreateMap<ContactViewModel, Contact>(MemberList.Source)
.EqualityComparison((src, dst) => src.Id == dst.Id)
.ForSourceMember(x => x.IsDeleted, opt => opt.Ignore())
.ForSourceMember(x => x.FullName, opt => opt.Ignore());

Files:

public class ArticleViewModel
{
    public int Id { get; set; }
    ... 
    public List<ImageViewModel> Images { get; set; }
}

public class Article : IEntity<int>
{
    public int Id { get; set; }
    ...
    public virtual ICollection<Image> Images { get; set; }  
}

public class ContactViewModel
{
    public int Id { get; set; }
    ... 
    public ImageViewModel Image { get; set; }
}

public class Contact: IEntity<int>
{
    [Key]
    public int Id { get; set; }

    ...

    public int? ImageId { get; set; }

    public Image Image { get; set; }

}

public class ImageViewModel
{
    public int Id { get; set; }

    public string Image { get; set; }

    public string ImageType { get; set; }

    public bool IsDeleted { get; set; }
}

public class Image : IEntity<int>
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }

    public DateTime Created { get; set; }

    public DateTime Updated { get; set; }

    public byte[] ImageBytes { get; set; }

    public string ImageType { get; set; }

    public int? ArticleId { get; set; }

    public virtual Article Article { get; set; }
}

Finally solved it, I had forgot to mark Image as virtual in Contact . After doing that everything started working out of the box.

public virtual Image Image { get; set; }

I think you need to tell your contact mapper in the config to explicitly use the mapping for the image vm. There might be one or two typos as I'm doing this from memory but it should be similar to:

.ForMember(x => x.Image, opt => opt.MapFrom(contact => Mapper.Map<ImageViewModel, Image>(contact.ImageVm);))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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