【问题标题】:Entity core Mapping entity types with join table实体核心 使用连接表映射实体类型
【发布时间】:2018-04-16 14:54:50
【问题描述】:

我已经开始使用实体核心,但遇到了一个问题。 我在我的项目中使用自动映射器,但不知道如何填充我的连接表(BookAuthor)。

在 MVC 中,我使用 ICollections,但实体核心还不支持使用多对多关系实体,现在我必须使用连接表。

问题:如何将我的 Bookviewmodel 映射到 Book? 我不知道应该如何处理我的 BookAuthors 列表。也许我不应该填充它?

我尝试了类似的方法,但它不起作用。

CreateMap<BookViewModel, Book>()
.ForMember(b => b.BookAuthors, opt => opt.MapFrom(b => b.Authors.Select(a => new BookAuthor
            {
                AuthorId = a.AuthorId
            }

模型(为简洁起见删除了一些属性)

 public class Book
{
    public int BookId { get; set; }

    public List<BookAuthor> BookAuthors { get; set; }
}
public class Author
    {
        public int AuthorId { get; set; }
        public string AuthorName { get; set; }
        public List<BookAuthor> BookAuthors { get; set; }
    }
 public class BookAuthor
{
    public int BookId { get; set; }
    public Book Book { get; set; }

    public int AuthorId { get; set; }
    public Author Author { get; set; }
}
public class BookViewModel
{
    public int BookId { get; set; }

    public virtual List<AuthorViewModel> Authors { get; set; }    
}
public class AuthorViewModel
    {
        public int AuthorId { get; set; }

        public string AuthorName { get; set; }
    }
public class Library : DbContext
{
    public DbSet<Book> Books { get; set; }

    public DbSet<Author> Authors { get; set; }
}

映射的工作版本

 .ForMember(dto => dto.Authors, opt => opt.MapFrom(b => b.BookAuthors.Select(a=>a.Author).ToList()));
        CreateMap<List<BookAuthor>, List<AuthorViewModel>>();
.PreserveReferences()//don't forget about this row or you will get an error
.ForMember(b => b.BookAuthors, opt => opt.MapFrom(b => b.Authors
    .Select(a => new { b.BookId, Book = b, a.AuthorId, Author = a })));

【问题讨论】:

  • 您应该设置AuthorId = a.AuthorId,而不是设置BookId = b.BookId。但是请注意,这仅在您添加新书时就足够了。通常不建议使用 AutoMapper 将视图模型映射到实体,因为这通常需要您不应该尝试将业务逻辑塞进映射配置中。
  • 我的导师说我不应该使用DTO的......添加书籍正是我所需要的。好的,我将设置 AuthorId,但我将如何处理另外 3 个属性?它们现在为空...
  • 我从来没有使用过连接表,对于愚蠢的问题非常抱歉。
  • 只需保存更改。 EF 将负责设置其他外键。当您从数据库中重读书籍时,包括BookAuthorsBook,EF 将填充所有属性。
  • 非常感谢。我会试试的。

标签: c# entity-framework asp.net-core automapper entity-framework-core


【解决方案1】:

这是所需的映射配置:

CreateMap<Book, BookViewModel>()
    // Book -> BookViewModel
    .ForMember(b => b.Authors, opt => opt.MapFrom(b => b.BookAuthors
        .Select(ba => ba.Author)))
    .ReverseMap()
    // BookViewModel -> Book
    .PreserveReferences()
    .ForMember(b => b.BookAuthors, opt => opt.MapFrom(b => b.Authors
        .Select(a => new { b.BookId, Book = b, a.AuthorId, Author = a })))
    ;

CreateMap<Author, AuthorViewModel>()
    // Author -> AuthorViewModel
    .ReverseMap()
    // AuthorViewModel -> Author
    ;

最重要的是要意识到 AutoMapper 不需要从 MapFrom 返回的表达式的 type 来匹配目的地的类型。如果不匹配,则 AutoMapper 将尝试使用相应的映射将返回的类型映射到目标类型(如果有)。这允许您重用映射。

为了将BookAuthor 转换为AuthorViewModel,首先将其转换为Author(通过简单地提取Author 属性),就像它是Author 的集合一样,然后让AM 转换@ 987654329@ 到 AuthorViewModel 使用对应的映射。

为了将AuthorViewModelBookViewModel.Authors 转换为BookAuthor,首先将其转换为类似于BookAuthor 的异常类型,但对应的BookAuthor 属性类型为ViewModel 类型和让 AM 使用相应的映射将其转换为 BookAuthorPreserveReferences() 用于避免由于循环引用模型导致的堆栈溢出。

【讨论】:

  • PreserveReferences 暂时不再需要 now
  • @LucianBargaoanu 好吧,我使用的是最新的 AM,如果我不指定 PreserveReferences,我仍然会遇到 SO 异常。
  • 它不起作用,因为涉及到动态映射。如果所有地图都是静态创建的,则不需要 PreserveReferences。我不知道修复它,我不是动态映射的粉丝。
  • 抱歉耽搁了。非常感谢,我会尽快测试(~3 天)。现在,让它成为答案。
  • 这个解决方案对我不起作用(作者仍然为空
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-01-10
  • 2017-06-30
  • 2021-11-18
  • 1970-01-01
  • 2020-01-27
  • 1970-01-01
  • 2019-10-28
相关资源
最近更新 更多