I am having a heck of a time converting from older mapping standards to automapper.
Here are my classes
// Models
public class BaseModel
{
public Int64 Id { get; set; }
public Guid UniqueId { get; set; }
public DateTime? CreateDate { get; set; }
public DateTime? LastUpdate { get; set; }
}
public class LibraryItemModel : BaseModel
{
public string Name { get; set; }
public string Description { get; set; }
public string URL { get; set; }
public bool IsActive { get; set; }
public List<LibraryCategoryModel> Categories { get; set; }
}
public class LibraryCategoryModel : BaseModel
{
public string Description { get; set; }
}
// Entity Classes
public partial class LibraryItem
{
public LibraryItem()
{
this.LibraryItemCategories = new HashSet<LibraryItemCategory>();
}
public long Id { get; set; }
public System.Guid UniqueId { get; set; }
public string Description { get; set; }
public string URL { get; set; }
public System.DateTime CreateDate { get; set; }
public System.DateTime LastUpdate { get; set; }
public bool IsActive { get; set; }
public string Name { get; set; }
public virtual ICollection<LibraryItemCategory> LibraryItemCategories { get; set; }
}
// comes from a ternary table in DB... many to many
public partial class LibraryItemCategory
{
public long LibraryItemId { get; set; }
public long LibraryCategoryId { get; set; }
public System.DateTime CreateDate { get; set; }
public System.DateTime LastUpdate { get; set; }
public virtual LibraryCategory LibraryCategory { get; set; }
public virtual LibraryItem LibraryItem { get; set; }
}
public partial class LibraryCategory
{
public LibraryCategory()
{
this.LibraryCategoryRoles = new HashSet<LibraryCategoryRole>();
this.LibraryItemCategories = new HashSet<LibraryItemCategory>();
}
public long id { get; set; }
public System.Guid UniqueId { get; set; }
public string Description { get; set; }
public System.DateTime CreateDate { get; set; }
public System.DateTime LastUpdate { get; set; }
public virtual ICollection<LibraryCategoryRole> LibraryCategoryRoles { get; set; }
public virtual ICollection<LibraryItemCategory> LibraryItemCategories { get; set; }
}
// Old Conversion code doing it the long way
private LibraryItemModel Convert(Entities.LibraryItem libraryItem)
{
var newLibraryItem = new LibraryItemModel
{
UniqueId = libraryItem.UniqueId,
Name = libraryItem.Name,
Description = libraryItem.Description,
URL = libraryItem.URL,
CreateDate = libraryItem.CreateDate,
LastUpdate = libraryItem.LastUpdate,
IsActive = libraryItem.IsActive,
Categories = new List<LibraryCategoryModel>()
};
foreach (var lc in libraryItem.LibraryItemCategories)
{
var newCategory = new LibraryCategoryModel
{
UniqueId = lc.LibraryCategory.UniqueId,
Description = lc.LibraryCategory.Description,
CreateDate = lc.LibraryCategory.CreateDate,
LastUpdate = lc.LibraryCategory.LastUpdate
};
newLibraryItem.Categories.Add(newCategory);
}
return newLibraryItem;
}
// My attempt at automapper to go between the models and entities
Mapper.CreateMap<EF.Entities.LibraryItem, LibraryItemModel>();
Mapper.CreateMap<LibraryItemModel, EF.Entities.LibraryItem>();
.ForMember(lim => lim.LibraryItemCategories, o => o.Ignore()
Mapper.CreateMap<EF.Entities.LibraryCategory, LibraryCategoryModel>();
Mapper.CreateMap<LibraryCategoryModel, EF.Entities.LibraryCategory>()
.ForMember(lcm => lcm.LibraryCategoryRoles, o => o.Ignore())
.ForMember(lcm => lcm.LibraryItemCategories, o => o.Ignore());
No matter how I configure ignores or custom mappings it seems to not like this nesting. Any Automapper experts out there who could tell me how a mapping with a complex object like this could be done. The enitity classes are being generated via an EF6 edmx file.
So basically the problem here is that you want to map from each LibraryItemCategory
that belongs to a LibraryItem
to a LibraryCategoryModel
that includes properties from each LibraryItemCatalog
's LibraryCatalog
property.
First you want to correctly map the collections to each other:
Mapper.CreateMap<LibraryItem, LibraryItemModel>()
.ForMember(
dest => dest.Categories,
opt => opt.MapFrom(src => src.LibraryItemCategories));
Next you need to worry about mapping each LibraryItemCategory
inside of LibraryItem.LibraryItemCategories
to a LibraryCatalogModel
. As stated in the problem, you need to access each LibraryItemCategory
's LibraryCatalog
property and actually map from that instead. The way this looks is:
Mapper.CreateMap<LibraryItemCategory, LibraryCategoryModel>()
.ConstructUsing(ct => Mapper.Map<LibraryCategoryModel>(ct.LibraryCategory))
.ForAllMembers(opt => opt.Ignore());
Here, we're telling AutoMapper that to map from a LibraryItemCategory
to a LibraryCategoryModel
, we need to construct LibraryCategoryModel
's using another call to Mapper.Map
on the inner LibraryCategory
property.
Next, all that's left to do is define the mapping from LibraryCategory
to LibraryCategoryModel
:
Mapper.CreateMap<LibraryCategory, LibraryCategoryModel>();
Now a call to Mapper.Map
on the LibraryItem
should take care of everything for you.
Alternatively, you could remove the map from LibraryItemCategory
to LibraryCategoryModel
and use LINQ to create the collection of LibraryCategory
s that you actually want to map from in the mapping definition from LibraryItem
to LibraryItemModel
:
Mapper.CreateMap<LibraryItem, LibraryItemModel>()
.ForMember(
dest => dest.Categories,
opt => opt.MapFrom(
src => src.LibraryItemCategories.Select(lb => lb.LibraryCategory)));
You'd obviously still need the mapping from LibraryCategory
to LibraryCategoryViewModel
, but you might prefer this since it involves fewer mappings.