简体   繁体   中英

Unable to map List<> navigational properties using OData, EF Core and AutoMapper

I'm currently writing an ASP .NET Core API utilizing OData for querying, and Entity Framework to talk to the database.

I want to separate the domain objects from the DTOs sent to the user, so have also started to use AutoMapper to translate entity framework query results to DTOs I have created.

At this point (while I'm testing), my DTOs and domain objects are the same - just public getter/setter properties. Examples of the DTOs are as follows:

    public class NoteDTO
    {
        public int Id { get; set; }
        public string Body { get; set; }
        public string Conclusion { get; set; }
        public string Title { get; set; }

        public ManagerDTO Manager { get; set; }
    }

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

        public virtual List<ProductDto> Products { get; set; }
    }

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

I also have a test method in my NotesController for fetching notes (again, using OData) which is as follows:

        [HttpGet]
        [EnableQuery]
        public IQueryable<NoteDTO> GetMeeting()
        {
            var config = new MapperConfiguration(cfg =>
            {
                cfg.CreateMap<Note, NoteDTO>();
                cfg.CreateMap<Product, ProductDto>();
                cfg.CreateMap<Manager, ManagerDTO>()
                    .ForMember(md => md.Products, conf => conf.MapFrom(m => m.Products));
            });
            return _context.Notes.ProjectTo<NoteDTO>(config);
        }

I then try and hit my API with the following query:

https://localhost:5001/api/Notes ?$select=Id,Body,Conclusion&$top=5&$expand=Manager($select=Id)

However, this fails, and in amongst the stack trace, I'm given the following error message:

System.ArgumentException: Expression of type 'System.Collections.Generic.IEnumerable`1[System.Tuple`3[TestEntityFramework.DataObjects.ProductDto,Microsoft.EntityFrameworkCore.Query.Internal.MaterializedAnonymousObject,Microsoft.EntityFrameworkCore.Query.Internal.MaterializedAnonymousObject]]' cannot be used for parameter of type 'System.Collections.Generic.IEnumerable`1[TestEntityFramework.DataObjects.ProductDto]' of method 'System.Collections.Generic.IEnumerable`1[TestEntityFramework.DataObjects.ProductDto] _ToEnumerable[ProductDto](System.Collections.Generic.IEnumerable`1[TestEntityFramework.DataObjects.ProductDto])'

If I remove the List from the ManagerDTO object and the relevant Product mapping config, the query above works successfully.

I saw this comment on a GitHub issue for what sounds like the same problem, but trying to implement the suggestion hasn't helped (assuming I've understood them correctly): https://github.com/AutoMapper/AutoMapper/issues/2853#issuecomment-482317381

Has anyone else run into this problem? I'm still getting used to AutoMapper so may have missed something obvious, but from searching around this seems to be a fairly uncommon issue and so pointers as to what's going on here have been hard to come by.

I'm open to any other suggestions as to what the best way of translating an OData query to entity framework, then back to a DTO is as well - if what I'm doing here isn't optimal!

Are you using the Automapper Collection Extensions? If not, this should solve your problem: https://github.com/AutoMapper/AutoMapper.Collection

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