When mapping Lists, if the DestinationType is added to a DataContext, automapper fails with an exception
k290 opened this issue · 1 comments
Source/destination types
public class SourceType
{
public int SomeNumber{ get; set; }
}
public class DestinationType
{
public int SomeNumber{ get; set; }
}
Mapping configuration
CreateMap<SourceType, DestinationType>()
Version: 10.1.1
Expected behavior
When mapping lists, exception is not thrown if the DestinationType happens to be added as a DbSet to the DbContext
Actual behavior
Exception is thrown
Steps to reproduce
Consider the following code mapping a List from the SourceType to the DestinationType:
var result= Mapper.Map<List<SourceType>, List<DestinationType>>(inputSource);
This works perfectly fine.
However when DestinationType is added to a DataContext as such
public class DataContext : BaseDbContext, INotificationDataContext
{
public DataContext(DbContextOptions<DataContext> options, IServiceProvider services) : base(options, services)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
}
public DbSet<DestinationType> DestinationTypes{ get; set; }
}
Then automapper fails with the below exception and stack trace when doing the mapping:
Object reference not set to an instance of an object.
Stack Trace:
at AutoMapper.Collection.Runtime.GeneratePropertyMapsFeature.<>c.b__5_0(PropertyMap pm)
at System.Linq.Enumerable.Any[TSource](IEnumerable1 source, Func
2 predicate)
at AutoMapper.Collection.Runtime.GeneratePropertyMapsFeature.CreateEquivalentExpression(IEnumerable1 propertyMaps) at AutoMapper.Collection.Runtime.GeneratePropertyMapsFeature.<>c__DisplayClass3_0.<Get>b__1(IGeneratePropertyMaps x) at System.Linq.Enumerable.SelectIListIterator
2.MoveNext()
at System.Linq.Enumerable.TryGetFirst[TSource](IEnumerable1 source, Func
2 predicate, Boolean& found)
at System.Linq.Enumerable.FirstOrDefault[TSource](IEnumerable1 source, Func
2 predicate)
at AutoMapper.Collection.Runtime.GeneratePropertyMapsFeature.<>c__DisplayClass3_0.b__0(TypePair _)
at System.Collections.Concurrent.ConcurrentDictionary2.GetOrAdd(TKey key, Func
2 valueFactory)
at AutoMapper.Collection.Runtime.GeneratePropertyMapsFeature.Get(TypeMap typeMap)
at AutoMapper.EquivalencyExpression.EquivalentExpressions.GetEquivalentExpression(IConfigurationProvider configurationProvider, TypeMap typeMap)
at AutoMapper.EquivalencyExpression.EquivalentExpressions.GetEquivalentExpression(IConfigurationObjectMapper mapper, Type sourceType, Type destinationType)
at AutoMapper.Mappers.EquivalentExpressionAddRemoveCollectionMapper.MapExpression(IConfigurationProvider configurationProvider, ProfileMap profileMap, IMemberMap memberMap, Expression sourceExpression, Expression destExpression, Expression contextExpression)
at AutoMapper.MapperConfiguration.GenerateObjectMapperExpression(MapRequest mapRequest, IObjectMapper mapperToUse)
at AutoMapper.MapperConfiguration.BuildExecutionPlan(MapRequest mapRequest)
at AutoMapper.MapperConfiguration.CompileExecutionPlan(MapRequest mapRequest)
at AutoMapper.Internal.LockingConcurrentDictionary2.<>c__DisplayClass2_1.<.ctor>b__1() at System.Lazy
1.ViaFactory(LazyThreadSafetyMode mode)
at System.Lazy1.ExecutionAndPublication(LazyHelper executionAndPublication, Boolean useDefaultConstructor) at System.Lazy
1.CreateValue()
at System.Lazy1.get_Value() at AutoMapper.Internal.LockingConcurrentDictionary
2.GetOrAdd(TKey key)
at AutoMapper.MapperConfiguration.GetExecutionPlan(MapRequest mapRequest)
at AutoMapper.MapperConfiguration.GetExecutionPlan[TSource,TDestination](MapRequest mapRequest)
at AutoMapper.Mapper.MapCore[TSource,TDestination](TSource source, TDestination destination, ResolutionContext context, Type sourceType, Type destinationType, IMemberMap memberMap)
at AutoMapper.Mapper.Map[TSource,TDestination](TSource source, TDestination destination)
at AutoMapper.Mapper.Map[TSource,TDestination](TSource source)
Note that if the DbSet is removed from the dbContext the mapping works perfectly fine. Also note that this is only an issue when mapping lists
This looks to be an issue with Equivalency expression when mapping types using AM.Collection.EF or EFCore.
It looks at DestinationType
to find Primary Key members and used maps with said key properties to generate an equivalency expression. This expression fails with these errors when no matches are present.
This is so when you want to update an existing item, or compare classes to each other you know which ones already exist in the database and can be updated, and which should be removed or deleted. You can also add EquivalencyExpression()
after create map to make your own comparison expression and that will fix the error message as well.