简体   繁体   中英

Automapper projection (EF) with encapsulated child collections

I use Automapper to map from EF entities to view models.

I now have this entity

public class MenuGroup : IEntity
{
    public int MenuGroupId { get; set; }

    protected ICollection<MenuGroupItem> _menuGroupItems { get; set; }
    public IEnumerable<MenuGroupItem> MenuGroupItems { get { return _menuGroupItems; } }

    public void AddMenuItem(MenuGroupItem menuGroupItem)
    {
        _menuGroupItems.Add(menuGroupItem);
    }
}

That is an encapsulated collection, I followed instructions here to make this work: http://lostechies.com/jimmybogard/2014/05/09/missing-ef-feature-workarounds-encapsulated-collections/

So I configure it like so this.HasMany(x => x.MenuGroupItems).WithRequired(x => x.BelongsTo).WillCascadeOnDelete(true);

Now the problem I get is when I try to use automapper to map my MenuGroup into a viewmodel.

I run this code: menuGroup = _context.MenuGroups.Project().To<MenuGroupEditModel>().Single(x => x.UniqueUrlFriendlyName == request.UniqueUrlFriendlyName);

and get this error: The specified type member 'MenuGroupItems' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported. The specified type member 'MenuGroupItems' is not supported in LINQ to Entities. Only initializers, entity members, and entity navigation properties are supported.


Now I can work with the collection, it saves correctly to the database and all is well there it's only when i want to user automapper here that it fails.

If I replace the protected ICollection and public IEnumerable with simply: public ICollection<MenuGroupItem> MenuGroupItems { get; set; } public ICollection<MenuGroupItem> MenuGroupItems { get; set; } public ICollection<MenuGroupItem> MenuGroupItems { get; set; } it works right away so the problem lies in automapping with my encapsulated collection.


Update: I also tried this menuGroup = _context.MenuGroups.Include(x => x.MenuGroupItems).Where(x => x.UniqueUrlFriendlyName == request.UniqueUrlFriendlyName).Project().ToSingleOrDefault<MenuGroupEditModel>(); with no difference other than that it errored in the ToSingleOrDefault instead.

Your problem is that Automapper can't modify MenuGroupItems because there is no public setter.

Your solution is changing it to this:

public IEnumerable<MenuGroupItem> MenuGroupItems { get; set; }

public void AddMenuItem(MenuGroupItem menuGroupItem)
{
    MenuGroupItems.Add(menuGroupItem);
}

After some more debugging I figured out the Config file looking like this

    public MenuGroupConfiguration()
    {
        this.HasMany(x => x.MenuGroupAssigments).WithRequired(x => x.BelongTo).WillCascadeOnDelete(true);

        this.HasMany(x => x.MenuGroupItems).WithRequired(x => x.BelongsTo).WillCascadeOnDelete(true);
    }

had not been included leading to that error that now makes sense.


I can add as a general tip that if you don't use auto-mapper for a query but still use your encapsulated collection remember that you have to call decompile for it to work.

like so

        var menuGroupsWithType =
            _context.MenuGroups.Include(x => x.MenuGroupItems).Include(x => x.MenuGroupAssigments).Where(x => x.MenuGroupAssigments.Any(y => y.AssignToAll == selectedStructureType))
                .OrderBy(x => x.Name).Decompile().ToList();

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