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

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

问题描述

我遇到了以下示例中反映的问题.我在 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 })));

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

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