AutoMapper - 整数列表到对象列表[关闭]

Posted

技术标签:

【中文标题】AutoMapper - 整数列表到对象列表[关闭]【英文标题】:AutoMapper - list of ints to list of objects [closed] 【发布时间】:2021-10-12 05:12:33 【问题描述】:

电影实体

    public class Movie
    
        [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
        public int Id  get; set; 
        public string Name  get; set; 
        public DateTime PublishDate  get; set; 
        public Genre Genre  get; set; 
        public int GenreId  get; set; 
        public Director Director  get; set; 
        public int DirectorId  get; set; 
        public List<Actor> Actors  get; set; 
        public decimal Price  get; set; 
    

CreateMovieM dto

    public class CreateMovieM
    
        public string Name  get; set; 
        public decimal Price  get; set; 
        public int DirectorId  get; set; 
        public int GenreId  get; set; 
        public string PublishDate  get; set; 
        public List<int> ActorsIds  get; set; 
    

映射配置文件

CreateMap<int, Actor>()
    .ForMember(dest => dest.Id, opt => opt.MapFrom(src => src));

CreateMap<CreateMovieM, Movie>()
     .ForMember(dest => dest.Actors, opt => opt.MapFrom(src => src.ActorsIds));

创建命令

public class CreateMovieCommand
    
        private readonly IMovieStoreDbContext _context;
        private readonly IMapper _mapper;
        private CreateMovieM _Model  get; set; 
        public CreateMovieCommand(IMovieStoreDbContext context, IMapper mapper, CreateMovieM model)
        
            _context = context;
            _mapper = mapper;
            _Model = model;
        

        public void Handle()
        
            var movie = _context.Movies.SingleOrDefault(x => x.Name == _Model.Name);
            if (movie is not null)
                throw new InvalidOperationException("Movie already exists");

            movie = _mapper.Map<Movie>(_Model);

            _context.Movies.Add(movie);
            _context.SaveChanges();
        
    

这是数据生成器

public class DataGenerator
    
        public static void Initialize(IServiceProvider services)
        
            using var context = new MovieStoreDbContext(
            services.GetRequiredService<DbContextOptions<MovieStoreDbContext>>());

            var a1 = new Actor  Id = 1, Name = "Kemal", Surname = "Sunal" ;
            var a2 = new Actor  Id = 2, Name = "Peri", Surname = "Baumeister" ;
            var a3 = new Actor  Id = 3, Name = "Daniel", Surname = "Radcliffe" ;

            var m1 = new Movie  Name = "Blood Red Sky", GenreId = 1, DirectorId = 2, Price = 10, PublishDate = new DateTime(1999, 5, 19), Actors = new List<Actor>  a2  ;
            var m2 = new Movie  Name = "Harry Potter", GenreId = 2, DirectorId = 3, Price = 15, PublishDate = new DateTime(1999, 5, 19), Actors = new List<Actor>  a3  ;
            var m3 = new Movie  Name = "Hababam Sinifi", GenreId = 3, DirectorId = 1, Price = 20, PublishDate = new DateTime(1999, 5, 19), Actors = new List<Actor>  a1  ;

            context.Movies.AddRange(
                new Movie  Id = 1, Name = "Blood Red Sky", GenreId = 1, DirectorId = 2, Price = 10, PublishDate = new DateTime(1999, 5, 19), Actors = new List<Actor>  a2  ,
                new Movie  Id = 2, Name = "Harry Potter", GenreId = 2, DirectorId = 3, Price = 15, PublishDate = new DateTime(1999, 5, 19), Actors = new List<Actor>  a3  ,
                new Movie  Id = 3, Name = "Hababam Sinifi", GenreId = 3, DirectorId = 1, Price = 20, PublishDate = new DateTime(1999, 5, 19), Actors = new List<Actor>  a1 , 
                );

            context.Genres.AddRange(
                new Genre  Id = 1, Name = "Action" ,
                new Genre  Id = 2, Name = "Science Fiction" ,
                new Genre  Id = 3, Name = "Comedy" 
                );

            context.Directors.AddRange(
                new Director  Id = 1, Name = "Ertem", Surname = "Egilmez" ,
                new Director  Id = 2, Name = "Peter", Surname = "Thorwarth" ,
                new Director  Id = 3, Name = "Chris", Surname = "Columbus" 
               );

            context.SaveChanges();
        
    

示例输入

   
    "name": "string",
    "price": 0,   
    "directorId": 1,   
    "genreId": 1,   
    "publishDate": "2020.1.1",   
    "actorsIds": [
       1   
     ]

我试图将整数 id 列表映射到 Actor 列表,并在我输入 actorid 1 时出现“已添加具有相同键的项目。键:1”错误,它是演员 id 之一。

那么我应该如何配置自动映射器来做到这一点?

【问题讨论】:

复制会有所帮助。创建一个gist,我们可以执行并看到失败。 欢迎来到 Stack Overflow。请通过tour 了解 Stack Overflow 的工作原理,并阅读How to Ask 了解如何提高问题的质量。然后edit您的问题将您的源代码包含为minimal reproducible example,可以由其他人编译和测试。还将数据库表的 SQL 语句添加到您的问题中。看起来您在数据库中已经存在的嵌套实体类上使用 Add()。不要在已经存在的实体上使用Add()。根据您的代码,您可能希望从 EF 上下文加载现有实体或仅设置 id。 @LucianBargaoanu github.com/sinanoral/MovieStoreWebApi 这是回购。您可以使用电影控制器 post 方法进行测试。样本输入 "name": "string", "price": 0, "directorId": 1, "genreId": 1, "publishDate": "2020.1.1", "actorsIds": [ 1 ] 一个 Stack Overflow 问题应该包含所有问题本身需要回答的信息。 这是添加新记录时非常常见的错误。确保现有实体附加为Unchanged 【参考方案1】:
foreach (var actor in movie.Actors)

    _context.Entry(actor).State = EntityState.Unchanged;

感谢@GertArnold,我通过在 SaveChanges() 方法之前添加该代码解决了我的问题

【讨论】:

以上是关于AutoMapper - 整数列表到对象列表[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 AutoMapper 使用 EntityFramework 使用嵌套列表更新对象?

Automapper 自定义解析器源成员到目标对象列表映射问题

Automapper - 如何重用对象而不是创建新对象(此对象在列表中)

AutoMapper - 将源列表映射到目标数组

Automapper 数据表到列表

0.AutoMapper