AutoMapper/AutoMapper.Collection.EFCore

Does collection mapping working in EF.Core ?

sebitsi opened this issue · 7 comments

Hi,

I'm trying to implement mapping like this:

Mapper.Map<List<UdpUser>, List<User>>(source, destination);

Configuration i'm using is:

private static void CreateMappingsInternal(IMapperConfigurationExpression configuration)
{
    configuration.AddCollectionMappers();

    configuration.CreateMap<UdpUser, User>().EqualityComparison((src, dst) =>
                src.Id == dst.Id );
}

After calling Map method i test changes like this

var xx = context.ChangeTracker.Entries().Where(e => e.State != EntityState.Unchanged).ToList();

Update works perfect, Changes are visible in xx variable and applied in SQL after calling SaveChanges() method.

If i try to insert or delete, xx variable is empty and nothing is sent to SQL.

What i'm doing wrong.
Please advice.

You can't update an existing list for insert or updating. Destination has to be the DB set in order to insert or update.

What AutoMapper is designed to do is have one parent object with child collections that will insert update and delete. So you get UdpUserParent with List<UdpUser> as a property and add/remove/update that, then save back to the database and it will insert/update/delete the Users in EF.Core.

https://github.com/AutoMapper/AutoMapper.Collection explains it in more detail for EF6 but the same functions apply.

Hi @TylerCarlson1
I'm not using unattached list.

Destination list is created like this:

var destination = context.Users
   .Where(u => u.TenantId == input.TennantID && u.Name != "admin")
   .ToList();

If I update one item in my source and then calling Map method, it updates coresponding item in destination. This change was detected by Changetracker and EntityState is changed.
This works OK.

Why update still works without parent object as you commented ?.

destination list is Unattached because of ToList(). At that point it's no longer tied to context.Users which is a DBSet. So when you remove from destination you are removing from that list and not from the DBSet, so EF.Core has no idea the items are being removed. Same with adding not showing up. The Update works because even though the destination list is not directly attached to EF.Core, each of the users are, so any changes to those will be detected by change tracker.

The way you would do this is get a Tenant class and have a list of Users from that. Get a single instance based off the ID, and then save that same instance back. All changes to Tenant.Users will be pushed into Change Tracker. Inserts/Updates/Deletes and inserts will be associated by TenantID to the Tenant class's ID.

This might not be optimal way for you however because you have additional Filter for not Admin which you would have to account for or pass along the admin User which you might not want to do.

If you are doing it with List of Users only then EF.Core isn't going to help in this situation.

Hi @TylerCarlson1

Thanks for your great explanation.
I was dealing with list and items and totaly forget how EF works.

Is there any milestone when your are going to release non beta version on nuget ?

I'm not sure when we resolve dependency injection configuration I guess.

@Tasteful Is there anything left that needs to be done?

@TylerCarlson1 In the #3 we have an option to rebuild how the options are configured but I think we can finish a version up and release that one without the options refactoring (that will be a breaking change in all AM.Collection packages when that will come) and then later refactor the configuration part in a separate release.

I can check the last part during the weekend, it is some small refactoring for the tests that we need to do with the new version of AM.Dependencyinjection-package.

OK thanks.
I'll release it then after those things get sorted out.