I have a very specific use-case. I have entities generated with EF6.1.3
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated from a template.
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace MyProject.Data
{
using System;
using System.Collections.Generic;
public partial class Market
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Market()
{
this.Company = new HashSet<Company>();
this.Partner = new HashSet<Partner>();
this.Activity = new HashSet<Activity>();
this.Product = new HashSet<Product>();
}
public int market_id { get; set; }
public string market_name { get; set; }
public int display_color { get; set; }
public bool is_modifiable { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Company> Company { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Partner> Partner { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Activity> Activity { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Product> Product { get; set; }
}
}
I also have a repository class that reads the generated entity types. In the next layer (Service) I use the repository and AutoMapper to map the entities to the desired types. For example I have a read method inside the MarketServices class
public ModelType Read<ModelType>(Expression<Func<Market, bool>> predicate)
{
var entity = Read(predicate);
var market = entityMapper.Map<ModelType>(entity);
return market;
}
With the appropriate mapping configurations this works flawlessly. Now, in another service I need to use the MarketServices (many-to-many relationship) because I want to add a new Company to a subset of already existing Markets. Things got furious from here, and there are no hidden details, I'm going to show everything: CompanyServices.Create:
public void CreateAndSave(CreateCompanyViewModel viewModel)
{
var entity = entityMapper.Map<Company>(viewModel);
if (viewModel.SelectedOperations != null)
{
foreach (var marketID in viewModel.SelectedOperations)
{
var marketModel = marketsProvider.Read<Market>(m => m.market_id == marketID);
entity.Market.Add(marketModel);
}
}
Create(entity);
}
The error pops at the marketsProvider.Read line. Yes, that would be the source and target types exactly the same. Everything else works, if I choose to use different mappings that I've defined it works. I defined this mapping like so:
config.CreateMap<Market, Market>();
So the repository returns the appropriate Market entities, but when I try to just "passthrough" them with AutoMapper I get the strangest (I'll be damned if I understand why you try to do that) exception I've ever seen:
Mapping types: Market_C126EFB65DDE81A0F02B0BF191A2C8B857DA7226E54AB43FB5DF74D3D3A406ED -> ICollection
1 System.Data.Entity.DynamicProxies.Market_C126EFB65DDE81A0F02B0BF191A2C8B857DA7226E54AB43FB5DF74D3D3A406ED -> System.Collections.Generic.ICollection
1[[MyProject.Data.Activity, MyProject, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]Destination path: Market.Activity.Activity
Source value: System.Data.Entity.DynamicProxies.Market_C126EFB65DDE81A0F02B0BF191A2C8B857DA7226E54AB43FB5DF74D3D3A406ED
So what exactly is happening here? Why won't Automapper return me the original object if both the source and target type of the mapping is the same? Is there any way to achieve this behavior?
Thanks!
I ended up using a partial solution found Can I get AutoMapper to return the same object sometimes? and I changed my Read function like so:
public ModelType Read<ModelType>(Expression<Func<Market, bool>> predicate) where ModelType: class
{
var entity = Read(predicate);
if (entity is ModelType)
{
return entity as ModelType;
}
return entityMapper.Map<ModelType>(entity);
}
I'm just gonna leave this here in case anyone else stumbles upon the same use case.