How to use select on domain model

asp.net-core c# domain-driven-design entity-framework-core

Question

I have entities that I map with automapper to domain models and return them from the service as Iqueryable. How can I use .Select or use automapper projectTo on them to map them to view models, because when I try I get thrown an error IAsyncEnumerable cannot be used for parameter of type IEnumerable on the navigation property inside the domain model?

class HomeDomainModel
{
    public string Id { get; set; }

    public ICollection<HumanDomainModel> Humans { get; set; }
}
class HumanDomainModel
{ 
    public string Id { get; set; }
}
class HomaEntity
{
    public string Id { get; set; }

    public ICollection<HumanEntity> Humans { get; set; }
}
class HumanEntity 
{
    public string Id { get; set; }
}
// IQueryable<HomeEntity>
var homeEntities = homeEntities.GetAll();

// IQueryable<HomeDomainModel>
var homeDomainModels = humanEntity.ProjectTo<HomeDomainModel>();

// Here it throws the exception
var homeViewModel = homeDomainModels.Select(hdm => new HomeViewModel()
    {
        Id = hdm.Id,
        HumansCount = hdm.Humans.Count()
    }).ToArrayAsync();
1
0
8/28/2019 8:59:27 AM

Popular Answer

If you want to map ICollection<HumanEntity> Humans { get; set; } to HumansCount, you could try code below:

  1. Profile

    public class ModelProfile: Profile
    {
        public ModelProfile()
        {
            CreateMap<HomaEntity, HomeViewModel>()
                .ForMember(dest => dest.HumansCount, opt => opt.MapFrom(src => src.Humans.Count));           
        }
    }
    
  2. Use Case

    var humanEntity = new List<HomaEntity> {
        new HomaEntity{ Id = "T1", Humans = new List<HumanEntity>(){
            new HumanEntity{ Id = "H1"},
        } },
        new HomaEntity{ Id = "TT1", Humans = new List<HumanEntity>(){
            new HumanEntity{ Id = "HH1"},
            new HumanEntity{ Id = "HH2"},
        } },
        new HomaEntity{ Id = "TT1", Humans = new List<HumanEntity>(){
            new HumanEntity{ Id = "HHH1"},
            new HumanEntity{ Id = "HHH2"},
            new HumanEntity{ Id = "HHH3"}
        } }
    };
    // Here it throws the exception
    var homeViewModels = _mapper.Map<List<HomeViewModel>>(humanEntity);
    

Update

For EF Core, it has a concept of mixed client/database evaluation in LINQ queries. For your code, HumansCount = hdm.Humans.Count() will run at client side and ToArrayAsync() will run as server side or async.

Here are two options for you:

  • Change .ToArrayAsync() to .ToArray()
  • For this limitation, it has been fixed in EF Core 3.0, if you need to use .ToArrayAsync(), you could try migrate your .net core 2.2 project to .net core 3.0 with using ef core 3.0 like version <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0-preview8.19405.11" />
0
8/29/2019 3:01:03 AM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow