The application is built with DDD approach, with a separate set of persistence models. I called database object, or dbo:
public class ParentDbo
{
public int ParentId { get; set; }
public int TypeId { get; set; }
}
public class ChildDbo
{
public int ChildId { get; set; }
public ParentDbo Parent { get; set; }
public int RetryNumber { get; set; }
}
We have a simple model to look at: a parent and a child relationship. The RetryNumber presents the enum value in the database.
On retrieving data, it uses Dapper to first query the database, and use its splitOn feature to map data into them. This part is irrelevant but I will show it anyway for completeness:
const string sql = "SELECT * FROM XXX ....";
using (var cnt = _dbConnectionFactory.CreateConnection())
{
var childDbos = await cnt.QueryAsync<ChildDbo, ParentDbo, ChildDbo>(
sql: sql,
map: (childDbo, parentDbo) =>
{
childDbo.Parent = parentDbo;
return childDbo;
},
splitOn: "ParentId"
);
}
Dapper has limitation that it couldn't map data to private complex objects. That's mainly the reason why I have to have 2 sets of models. I would like to encapsulate the data and logic within domain models, with private setters and other techniques.
Here are my domain models:
public class Parent
{
public int Id { get; private set; }
public int TypeId { get; private set; }
public Parent(int parentId, int typeId)
{
// Validations
this.Id = parentId;
this.TypeId = typeId;
}
}
public class Child
{
public int Id { get; private set; }
public Parent Parent { get; private set; }
public Attempt Attempt { get; private set; }
public Child(int childId, Parent parent, Attempt attempt)
{
// Validations
this.Id = childId;
this.Parent = parent;
this.Attempt = attempt;
}
}
For domain models, I don't want public setters, and parameter-less constructors.
The Attempt is the enum with integer backing values:
public enum Attempt
{
Original = 1,
FirstRetry = 2,
SecondRetry = 3,
LastRetry = 4
}
Lastly, I want to use AutoMapper to map between Dbos and the domain models. Here is the mapping:
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Child, ChildDbo>()
.ForMember(dest => dest.ChildId, opts => opts.MapFrom(src => src.Id))
.ForMember(dest => dest.RetryNumber, opts => opts.MapFrom(src => (int)src.Attempt))
.ReverseMap();
CreateMap<Parent, ParentDbo>()
.ForMember(dest => dest.ParentId, opts => opts.MapFrom(src => src.Id))
.ReverseMap();
}
}
I want to have two-ways mappings so I use ReverseMap().
.Net Fiddle demo: https://dotnetfiddle.net/saEHWd
It maps domain models to dbos without problem:
But its reverse, mapping from dbos to domain models, is throwing exceptions:
Unhandled exception. System.ArgumentException: Program+Child needs to have a constructor with 0 args or only optional args. (Parameter 'type') at lambda_method18(Closure , Object , Child , ResolutionContext ) 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[TDestination](Object source) at Program.Main()
I've tried to remove the enum property and everything worked so I'm pretty sure it's the enum mapping that's having issues.

As far as I can see in your fiddle you are trying to map from
ChildDbotoParentand there is no mapping setup for it. Change the mapping code to:And since there is mismatch in third
Child's ctor param and source property names change map to:See here
Or rename third
Child's ctor parameter toretryNumber:see here.
or use
ForCtorParam:Here.