sziszu sziszu - 3 years ago 205
C# Question

AutoMapper mapping ICollection with EF

I'm trying to map nested ICollection of one of my models to existing Dto, but I'm struggling to Map it properly with AutoMapper

Models:

public class Ingredient : BaseEntity<long>
{
[MaxLength(100)]
public string Name { get; set; }
[ForeignKey("Id")]
public int CustomerId { get; set; }
public bool IsPackaging { get; set; }
public virtual ICollection<ProductIngredient> ProductIngredient { get; set; }
public virtual ICollection<IngredientComposition> IngredientComposition { get; set; }
}


Collection Model:

public class IngredientComposition : BaseEntity<int>
{
[MaxLength(20)]
public string Type { get; set; }
[MaxLength(200)]
public string Key { get; set; }
[MaxLength(200)]
public string Value { get; set; }
}


Dto:

public class IngredientDto
{
public long Id { get; set; }
public DateTime CretedOn { get; set; }
public DateTime UpdatedOn { get; set; }
public string Name { get; set; }
public int CustomerId { get; set; }
public int UsedCount { get; set; }
public bool IsPackaging { get; set; }
public IList<Composition> Ingredients { get; set; }
}

public class Composition
{
public string Type { get; set; }
public string Key { get; set; }
public string Value { get; set; }
}


My maps looks as follows as I'm struggling to properly set "ForMemeber" method(s):

CreateMap<Ingredient, IngredientDto>();
CreateMap<IngredientDto, Ingredient>();


Any help much appropriated!
Thanks

EDIT:

This is how I'm getting data:

return await _context.Ingredients
.Where(i => i.CustomerId ==_userResolverService.GetCustomerId())
.Include(i => i.IngredientComposition)
.Select(i => _mapper.Map<Ingredient, IngredientDto>(i))
.OrderBy(i => i.Name)
.ToListAsync();

Answer Source

First, you must do add CreateMap<IngredientComposition, Composition>(); and after doing this you must do change your Linq Query. You can use AutoMapper.EF6

return _context.Ingredients
                 .Where(i => i.CustomerId ==_userResolverService.GetCustomerId())
                 .Include(i => i.IngredientComposition)
                 .ProjectToList<IngredientDto>();

after use this you donot need use Select.

note: donot forget add _mapper.ConfigurationProvider in ProjectToList

ProjectToList<IngredientDto>(_mapper.ConfigurationProvider);

if you don't set it to get this Exception:

Mapper not initialized. Call Initialize with Appropriate configuration. If you are trying to use mapper instances through a container or otherwise, make sure you do not have any calls to the static Mapper.Map methods, and if you're using ProjectTo or UseAsDataSource extension methods, make sure you pass in the appropriate IConfigurationProvider instance.

more detail.

Update: your properties must have the same name.if you change Dto property Ingredients to IngredientComposition don't need use ForMember.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download