自动映射(使用AutoMapper)从DTO到其中具有多对多关系的实体 [英] Auto mapping (with AutoMapper) from DTO to an entity with many-to-many relationship in it

查看:348
本文介绍了自动映射(使用AutoMapper)从DTO到其中具有多对多关系的实体的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了以下示例中反映的问题.我已经在BookController中创建了一个POST方法来创建Book实体:

I'm having a problem that is reflected in the following example. i've created a POST method in my BookController to create a Book entity:

这是我的代码:

public class Book
{
    public int BookId { get; set; }
    public string Title { get; set; }
    public virtual ICollection<BookCategory> BookCategories { get; set; }
}

public class BookCategory
{
    public int BookId { get; set; }
    public virtual Book Book { get; set; }
    public int CategoryId { get; set; }
    public virtual Category Category { get; set; }
}

我的DTO:

public class BookDto
{
    public int BookId { get; set; }
    public string Title { get; set; }

    public ICollection<CategoryDto> Categories { get; set; }
}

public class CategoryDto
{
    public int CategoryId { get; set; }
    public string CategoryName { get; set; }
}

自动映射器配置:

        CreateMap<Book, BookDto>().ReverseMap();
        CreateMap<BookCategory, CategoryDto>()
            .ForMember(d => d.CategoryId, opt => opt.MapFrom(s => s.CategoryId))
            .ForMember(d => d.CategoryName, opt => opt.MapFrom(s => s.Category.CategoryName));
        CreateMap<CategoryDto, BookCategory>().ForMember(d => d.CategoryId, opt => opt.MapFrom(s => s.CategoryId));

        CreateMap<BookDto, Book>().AfterMap((s, d) =>
        {
            foreach (var bookCategory in d.BookCategories)
            {
                bookCategory.BookId = s.BookId;
            }
        });

这是我要映射到实体的DTO:

this is the DTO i'm trying to map to entity:

        BookDto model = new BookDto()
        {
            Title = "Test book",
            Categories = new List<CategoryDto>()
            {
                new CategoryDto()
                {
                    CategoryId = 1,
                    CategoryName = "drama"
                }
            },
        };

BookDto是一本新书,但是它指向现有的类别.在数据库中已经存在Category.Id = 1,其中"drama"作为CategoryName.当前的问题出在映射中:

BookDto is a new book, however it points to an existing Category. In database there is already Category.Id = 1 with "drama" as CategoryName. Current problem is in the mapping:

    CreateMap<BookDto, Book>().AfterMap((s, d) =>
    {
        foreach (var bookCategory in d.BookCategories)
        {
            bookCategory.BookId = s.BookId;
        }
    });

当上面的代码将要执行时,d.BookCategories为null.所以我想知道我的映射有什么问题吗?

when the above code is about to execute, d.BookCategories is null. So i wonder what's wrong my mapping?

推荐答案

AutoMapper自动映射具有相同名称的成员.由于BookBookDto中的集合具有不同的名称(BookCategoriesCategories),因此必须显式映射它们.您可以在其中一张地图中进行操作,ReverseMap将处理相反的情况:

AutoMapper maps automatically members with the same name. Since collections in Book and BookDto have different names (BookCategories vs Categories), they have to be mapped explicitly. You can do it in one of the maps and ReverseMap will handle the opposite:

CreateMap<Book, BookDto>()
    .ForMember(d => d.Categories, opt => opt.MapFrom(s => s.BookCategories))
    .ReverseMap()
    .AfterMap((s, d) =>
    {
        foreach (var bookCategory in d.BookCategories)
            bookCategory.BookId = s.BookId;
    });

但是由于联接实体仅包含2个id,因此您可以避免从CategoryDtoBookCategoryAfterMap的映射,并使用简单的LINQ投影(`Select')进行反向映射:

But since the join entity contains simply 2 ids, you can avoid the map from CategoryDto to BookCategory and AfterMap, and do the reverse mapping with simple LINQ projection (`Select'):

CreateMap<Book, BookDto>()
    .ForMember(d => d.Categories, opt => opt.MapFrom(s => s.BookCategories))
    .ReverseMap()
    .ForMember(d => d.BookCategories, opt => opt.MapFrom(s => s.Categories
        .Select(c => new BookCategory { BookId = s.BookId, CategoryId = c.CategoryId })));

这篇关于自动映射(使用AutoMapper)从DTO到其中具有多对多关系的实体的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆