I am trying to include Automapper into project using Entity Framework, this is my DTO class:
public class FunctionDto
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public string Comment { get; set; }
public DateTime? ExaminationDate { get; set; }
public string Place { get; set; }
}
And domain class with code first:
public class Function
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime? StartDate { get; set; }
public DateTime? EndDate { get; set; }
public string Comment { get; set; }
public DateTime? ExaminationDate { get; set; }
public string Place { get; set; }
public virtual List<Employee> Employees { get; set; }
}
Automapper configuration:
public static class AutoMapperConfiguration
{
public static void Configure()
{
Mapper.Initialize(config => config.AddProfile<FunctionProfile>());
}
}
public class FunctionProfile : Profile
{
protected override void Configure()
{
CreateMap<Function, FunctionDto>()
.ForMember(dto => dto.Id, opt => opt.MapFrom(src => src.Id))
.ForMember(dto => dto.Name, opt => opt.MapFrom(src => src.Name))
.ForMember(dto => dto.Comment, opt => opt.MapFrom(src => src.Comment))
.ForMember(dto => dto.StartDate, opt => opt.MapFrom(src => src.StartDate))
.ForMember(dto => dto.EndDate, opt => opt.MapFrom(src => src.EndDate))
.ForMember(dto => dto.ExaminationDate, opt => opt.MapFrom(src => src.ExaminationDate))
.ForMember(dto => dto.Place, opt => opt.MapFrom(src => src.Place));
}
}
Then use in WebApi:
var functionDtos = functions
.AsQueryable()
.OrderBy(sort)
.Skip(start)
.Take(count)
.ToList()
.Select(Mapper.Map<FunctionDto>);
Of course I have register in Global:
AutoMapperConfiguration.Configure();
But I got the exception:
Missing type map configuration or unsupported mapping
What is wrong with the code above?
Can you please confirm what functions is as the following passes:
MapperConfiguration.cs
namespace StackOverflow.Function
{
using AutoMapper;
public class MyProfile : Profile
{
protected override void Configure()
{
CreateMap<Function, FunctionDto>();
}
}
}
MappingTests.cs
[TestFixture]
public class MappingTests
{
[Test]
public void AutoMapper_Configuration_IsValid()
{
Mapper.Initialize(m => m.AddProfile<MyProfile>());
Mapper.AssertConfigurationIsValid();
}
[Test]
public void AutoMapper_Mapping_IsValid()
{
Mapper.Initialize(m => m.AddProfile<MyProfile>());
Mapper.AssertConfigurationIsValid();
var functions = new List<Function>
{
new Function
{
Comment = "Stack Overflow Rocks",
EndDate = new DateTime(2012, 01, 01),
ExaminationDate = new DateTime(2012, 02, 02),
Id = 1,
Name = "Number 1",
Place = "Here, there and everywhere",
StartDate = new DateTime(2012, 03, 03)
},
new Function
{
Comment = "As do I",
EndDate = new DateTime(2013, 01, 01),
ExaminationDate = new DateTime(2013, 02, 02),
Id = 2,
Name = "Number 2",
Place = "Nowhere",
StartDate = new DateTime(2013, 03, 03)
}
};
var functionDtos = functions
.AsQueryable()
.OrderBy(x => x.Id)
.Skip(1)
.Take(1)
.ToList()
.Select(Mapper.Map<FunctionDto>);
Assert.That(functionDtos, Is.Not.Null);
Assert.That(functionDtos.Count(), Is.EqualTo(1));
Assert.That(functionDtos.First().Id, Is.EqualTo(2));
}
}
Try this Configure() method,
Note: If the Function, FunctionDto has same name properties you do not need to map. AutoMapper will take care mapping.
protected override void Configure()
{
CreateMap<Function, FunctionDto>().IgnoreAllNonExisting();
}
--
public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
var sourceType = typeof(TSource);
var destinationType = typeof(TDestination);
var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType) && x.DestinationType.Equals(destinationType));
foreach (var property in existingMaps.GetUnmappedPropertyNames())
{
expression.ForMember(property, opt => opt.Ignore());
}
return expression;
}
Related
I am trying to map a source list to a destination array using AutoMapper.
Source classes
public class ReservationSource
{
public Travel TravelSource { get; set; }
public string SeqNo { get; set; }
}
public class Travel
{
public string TravelId { get; set; }
public ICollection<Trip> Trips { get; set; }
}
public class Trip
{
public string TrainNumber { get; set; }
public string Arrival { get; set; }
}
Destination classes
public class ReservationDestination
{
public Route[] TravelDest { get; set; }
public string SeqNumber { get; set; }
}
public class Route
{
public string SequNumber { get; set; }
public string RouteId { get; set; }
}
private static route[] GetRoutes(ICollection<Trip> trips)
{
List<route> routeList = new List<route>();
foreach (var trip trips)
{
var route = new route
{
SequNumber = trip.trainNumber
};
routeList.Add(route);
}
return routeList.ToArray();
}
Map configuration
cfg.CreateMap<ReservationSource, ReservationDestination>()
var config = new MapperConfiguration(cfg =>
{
cfg.AllowNullDestinationValues = true;
cfg.CreateMap<ReservationSource, ReservationDestination>()
.ForMember(dest => dest.SeqNumber, o => o.MapFrom(src => SeqNo))
.ForPath(dest => dest.TravelDest, o => o.MapFrom(src => GetRoutes(src)));
});
This is what I have tried, here I would like to eliminate the GetRoutes method where I will do a manual map using a foreach loop. Is it possible to use any other way without a loop?
Add mapping for Trip and Route classes.
cfg.CreateMap<Trip, Route>()
.ForMember(dest => dest.SequNumber, o => o.MapFrom(src => src.TrainNumber));
Complete Mapping Configuration
var config = new MapperConfiguration(cfg =>
{
cfg.CreateMap<Trip, Route>()
.ForMember(dest => dest.SequNumber, o => o.MapFrom(src => src.TrainNumber));
cfg.AllowNullDestinationValues = true;
cfg.CreateMap<ReservationSource, ReservationDestination>()
.ForMember(dest => dest.SeqNumber, o => o.MapFrom(src => src.SeqNo))
.ForPath(dest => dest.TravelDest, o => o.MapFrom(src => src.TravelSource.Trips));
});
IMapper mapper = config.CreateMapper();
var source = new ReservationSource
{
SeqNo = "Seq001",
TravelSource = new Travel
{
TravelId = "1",
Trips = new List<Trip>
{
new Trip { TrainNumber = "A0001" },
new Trip { TrainNumber = "B0001" }
}
}
};
var destination = mapper.Map<ReservationSource, ReservationDestination>(source);
Console.WriteLine(JsonConvert.SerializeObject(destination));
Sample Program
Output
{"TravelDest":[{"SequNumber":"A0001","RouteId":null},{"SequNumber":"B0001","RouteId":null}],"SeqNumber":"Seq001"}
References
Lists and Arrays - AutoMapper documentation
I'm trying to map a class (TrackingKeyStatic<T>) using c# and automapper.
TrackingKeyStatic<T> has the interface IBatchProcessing is inherited from Trackingkey<T> which has the interface ITrackingKey.
So by definition TrackingKeyStatic<T> is IBatchProcessing and ITrackingKey.
Automapper working fine with only one interface (IBatchProcessing)
But can't be mapped/be detect with interface ITrackingKey
I've created a fiddle to demonstrate https://dotnetfiddle.net/TO21PI
So the question is how can I map source with two interface to a concrete type<T>?
I've tried with this config, and it didn't work (which is the problem)
cfg.CreateMap<ITrackingKey, MyEntitiesDbFirstModel>()
I've tried to change the automapper config for
cfg.CreateMap<TrackingKeyStatic<NotReleventClassForThisExample>, MyEntitiesDbFirstModel>()
As demonstrate in Method TestWitTrackingKeyStaticAsSource_WORKING() its working just fine. But I can't really make a mapping for each subclass
I've tried to use method like .Include or .IncludeAllDerived, it didn't work, but I'm not quite sure if I need to use them here? Maybe I did it wrong?
Here's the unit tests I wrote for this question
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace StackOverflow
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestWithItrackingAsSource_NOTWORKING()
{
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<ITrackingKey, MyEntitiesDbFirstModel>()
.ForMember(d => d.TrackingKey, o => o.MapFrom(s => s.NewTrackingKey));
cfg.CreateMap<IBatchProcessing, MyEntitiesDbFirstModel>()
.ForMember(d => d.Skip, o => o.MapFrom(s => s.Skip))
.ForMember(d => d.Take, o => o.MapFrom(s => s.Take))
.ForMember(d => d.Total, o => o.MapFrom(s => s.Total));
});
var mapper = config.CreateMapper();
var source = new TrackingKeyStatic<NotReleventClassForThisExample>()
{
Skip = 10,
Take = 50,
Total = 123456,
NewTrackingKey = 987654
};
var actual = mapper.Map<MyEntitiesDbFirstModel>(source);
Assert.AreEqual(10, actual.Skip);//ok
Assert.AreEqual(50, actual.Take);//ok
Assert.AreEqual(123456, actual.Total);//ok
Assert.AreEqual(987654, actual.TrackingKey);//failed
}
[TestMethod]
public void TestWitTrackingKeyStaticAsSource_WORKING()
{
var config = new MapperConfiguration(cfg => {
cfg.CreateMap<TrackingKeyStatic<NotReleventClassForThisExample>, MyEntitiesDbFirstModel>()
.ForMember(d => d.TrackingKey, o => o.MapFrom(s => s.NewTrackingKey));
cfg.CreateMap<IBatchProcessing, MyEntitiesDbFirstModel>()
.ForMember(d => d.Skip, o => o.MapFrom(s => s.Skip))
.ForMember(d => d.Take, o => o.MapFrom(s => s.Take))
.ForMember(d => d.Total, o => o.MapFrom(s => s.Total));
});
var mapper = config.CreateMapper();
var source = new TrackingKeyStatic<NotReleventClassForThisExample>()
{
Skip = 10,
Take = 50,
Total = 123456,
NewTrackingKey = 987654
};
var actual = mapper.Map<MyEntitiesDbFirstModel>(source);
Assert.AreEqual(10, actual.Skip);//ok
Assert.AreEqual(50, actual.Take);//ok
Assert.AreEqual(123456, actual.Total);//ok
Assert.AreEqual(987654, actual.TrackingKey);//work fine
}
}
public interface ITrackingKey
{
int NewTrackingKey { get; set; }
List<object> Records { get; set; }
}
public interface IBatchProcessing
{
int Skip { get; set; }
int Take { get; set; }
int Total { get; set; }
}
public class TrackingKey<T> : ITrackingKey
{
private List<object> _records;
public int NewTrackingKey { get; set; }
public List<T> Records //not relevant for question, it just for implementing interface
{
get { return _records?.Cast<T>()?.ToList(); }
set { _records = value?.Cast<object>()?.ToList(); }
}
List<object> ITrackingKey.Records //not relevant for question, it just for implementing interface
{
get { return _records; }
set { _records = value; }
}
}
public class TrackingKeyStatic<T> : TrackingKey<T>, IBatchProcessing
{
public int Skip { get; set; }
public int Take { get; set; }
public int Total { get; set; }
}
public class MyEntitiesDbFirstModel
{
public int Skip { get; set; }
public int Take { get; set; }
public int Total { get; set; }
public int TrackingKey { get; set; }
}
public class NotReleventClassForThisExample { public int MyProperty { get; set; }}
}
I was able to get it working with a small "hacky" wrapper method:
public static MyEntitiesDbFirstModel MapToMyDbModel<T>(TrackingKeyStatic<T> trackingKey, IMapper mapper)
{
var interimTypeObject = new TrackingKey<T>()
{
NewTrackingKey = trackingKey.NewTrackingKey
};
var actual = mapper.Map<MyEntitiesDbFirstModel>(trackingKey);
mapper.Map<ITrackingKey, MyEntitiesDbFirstModel>(interimTypeObject, actual);
return actual;
}
Here's the fiddle for it - https://dotnetfiddle.net/XAjQB4
You may be able get rid of uglyness further - it seems that AutoMapper is not able to choose the correct map here when you use TrackingKeyStatic<T> but has no problems doing TrackingKey<T>.
I have a DTO class in my project. So, when I run in run time I have this message:
The specified cast from a materialized 'System.Double' type to the
'System.Single' type is not valid.
This message appear when I put float or double type only. I mapped my DTO class, but the error continue. With decimal or int work fine. This is my DTO class:
public class LiberacaoItensDTO
{
public LiberacaoItensDTO()
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<LiberacaoItensDTO, Liberacao>()
.ForMember(d => d.DataLib, opt => opt.MapFrom(src => Convert.ToDateTime(DataLib)));
cfg.CreateMap<LiberacaoItensDTO, Liberacao>()
.ForMember(d => d.Juros, opt => opt.MapFrom(src => Juros.ToString("C2")));
cfg.CreateMap<LiberacaoItensDTO, Liberacao>()
.ForMember(d => d.Desconto, opt => opt.MapFrom(src => Desconto.ToString("C2")));
cfg.CreateMap<LiberacaoItensDTO, Liberacao>()
.ForMember(d => d.Acrescimo, opt => opt.MapFrom(src => Acrescimo.ToString("C2")));
cfg.CreateMap<LiberacaoItensDTO, Liberacao>()
.ForMember(d => d.Vencimento, opt => opt.MapFrom(src => Convert.ToDateTime(Vencimento)));
cfg.CreateMap<LiberacaoItensDTO, Liberacao>()
.ForMember(d => d.Entrada, opt => opt.MapFrom(src => Entrada.ToString("C2")));
cfg.CreateMap<LiberacaoItensDTO, ItensLib>()
.ForMember(d => d.Qtde, opt => opt.MapFrom(src => Qtde.ToString("C2")));
cfg.CreateMap<LiberacaoItensDTO, ItensLib>()
.ForMember(d => d.Unitario, opt => opt.MapFrom(src => Unitario.ToString("C2")));
cfg.CreateMap<LiberacaoItensDTO, ItensLib>()
.ForMember(d => d.Custo, opt => opt.MapFrom(src => Custo.ToString("C2")));
cfg.CreateMap<LiberacaoItensDTO, ItensLib>()
.ForMember(d => d.CustoDiario, opt => opt.MapFrom(src => CustoDiario.ToString("C2")));
cfg.CreateMap<LiberacaoItensDTO, ItensLib>()
.ForMember(d => d.UltCondicao, opt => opt.MapFrom(src => UltCondicao.ToString("C2")));
cfg.CreateMap<LiberacaoItensDTO, ItensLib>()
.ForMember(d => d.Total, opt => opt.MapFrom(src => Total.ToString("C2")));
});
}
public int IdLiberacao { get; set; }
[DefaultValue(0)]
public int IdOrcamento { get; set; }
[DefaultValue(0)]
public int IdVendedor { get; set; }
public string Vendedor { get; set; }
public int IdFilial { get; set; }
public string Filial { get; set; }
[DefaultValue(0)]
public float DataLib { get; set; }
public int IdCliente { get; set; }
public string Cliente { get; set; }
public string TipoVenda { get; set; }
[DefaultValue(0)]
public float Juros { get; set; }
[DefaultValue(0)]
public float Desconto { get; set; }
[DefaultValue(0)]
public float Vencimento { get; set; }
[DefaultValue(0)]
public float Acrescimo { get; set; }
[DefaultValue(0)]
public float Entrada { get; set; }
public string Mensagem { get; set; }
public int IdProduto { get; set; }
public string Produto { get; set; }
[DefaultValue(0)]
public float Qtde { get; set; }
[DefaultValue(0)]
public float Unitario { get; set; }
[DefaultValue(0)]
public float Custo { get; set; }
[DefaultValue(0)]
public float CustoDiario { get; set; }
[DefaultValue(0)]
public float UltCondicao { get; set; }
[DefaultValue(0)]
public float Total { get; set; }
}
below my method. This method return a DTO object type:
public List<LiberacaoItensDTO> getAutoriza(int idorcamento)
{
var lista = contexto.Liberacoes
//.Where(lib => lib.IdOrcamento == idorcamento)
.Join(contexto.ItensLibs, lib => lib.IdOrcamento, itens => itens.IdOrcamento, (lib,itens) => new { lib, itens})
.Where(a => a.lib.IdOrcamento == a.itens.IdOrcamento && a.lib.IdOrcamento == idorcamento)
.Select(libera => new LiberacaoItensDTO
{
TipoVenda = libera.lib.TipoVenda,
IdOrcamento = libera.lib.IdOrcamento,
Juros = libera.lib.Juros != 0 ? libera.lib.Juros : 0,
//Entrada = libera.lib.Entrada != 0 ? libera.lib.Entrada : 0,
//Acrescimo = libera.lib.Acrescimo != 0 ? libera.lib.Acrescimo : 0,
//Desconto = libera.lib.Desconto != 0 ? libera.lib.Desconto : 0,
Mensagem = libera.lib.Mensagem,
//DataLib = libera.lib.DataLib != 0 ? libera.lib.DataLib : 0,
Qtde = libera.itens.Qtde != 0 ? libera.itens.Qtde : 0,
Vendedor = libera.lib.Vendedor,
Cliente = libera.lib.Cliente,
Filial = libera.lib.Filial
}).ToList();
return lista;
}
And my rest service:
public class LiberacaoController : ApiController
{
AutorizadorContext contexto = new AutorizadorContext();
PedidoLiberacao liberacao = new PedidoLiberacao();
[AcceptVerbs("Get")]
public IEnumerable<LiberacaoItensDTO> getLiberacao()
{
return liberacao.getAutoriza(1000012093).AsEnumerable().ToList();
}
}
If I comment this line Juros = libera.lib.Juros != 0 ? libera.lib.Juros : 0, or other with float field, work fine. Otherwise not.
If in your database side datatype contains float then take double in your code side to mapping.
I got this error too ,and I have float fields in the class(like your DTO class)
public class ReportArchiveHistoryQueryModel
{
public DateTime ArchiveDate { get; set; }
public float Energy { get; set; }
}
and I have sql table which contain float column.When I get some data via stored procedure ,
CREATE PROCEDURE [dbo].[sp_ReportArchiveHistory]
#SmartCounterId VARCHAR(10)
,#StartDate SMALLDATETIME
,#EndDate SMALLDATETIME
AS
SELECT ArchiveDate,Energy FROM Archive
WHERE Archive.SmartCounterId=#SmartCounterId
AND Archive.ArchiveDate>=#StartDate
AND Archive.ArchiveDate<=#EndDate
I got this error at return result.ToList();
public List<ReportArchiveHistoryQueryModel> ArchiveHistory(short smartCounterId, DateTime startDate,DateTime endDate)
{
var pSmartCounterId = new SqlParameter("SmartCounterId",smartCounterId);
var pStartDate = new SqlParameter("StartDate",startDate);
var pEndDate = new SqlParameter("EndDate ", endDate);
var result = this.Database.SqlQuery<ReportArchiveHistoryQueryModel>("exec dbo.sp_ReportArchiveHistory #SmartCounterId, #StartDate, #EndDate", pSmartCounterId, pStartDate, pEndDate);
return result.ToList();
}
So I solved the problem as below:
I think C# can't convert the data of float column to float field of class. Therefore I converted the float data which in the stored procedure to varchar.
CREATE PROCEDURE [dbo].[sp_ReportArchiveHistory]
#SmartCounterId VARCHAR(10)
,#StartDate SMALLDATETIME
,#EndDate SMALLDATETIME
AS
SELECT ArchiveDate,CONVERT(varchar(10), Energy )as Energy FROM Archive
WHERE Archive.SmartCounterId=#SmartCounterId
AND Archive.ArchiveDate>=#StartDate
AND Archive.ArchiveDate<=#EndDate
After I changed the float field with string.
My query model:
public class ReportArchiveHistoryQueryModel
{
public DateTime ArchiveDate { get; set; }
public string Energy { get; set; }
}
After when I need as float then I parsed again to float.
ReportArchiveHistoryBusinessModel reportArchiveHistoryBusinessModel=new ReportArchiveHistoryBusinessModel();
reportArchiveHistoryBusinessModel.ArchiveDate = item.ArchiveDate;
reportArchiveHistoryBusinessModel.Energy = float.Parse(item.Energy);
OR second solution:
just I changed float field to double :)
public class ReportArchiveHistoryQueryModel
{
public DateTime ArchiveDate { get; set; }
public double Energy { get; set; }
}
I solved changed all float and double field to string in my DTO class and in my App I change to float and double again.
Mapper.Initialize(cfg =>
{
cfg.CreateMap<ObjectDTO, Object>().ForMember(obj => obj.LastUpdateDate, opt =>
opt.Condition(pre => pre.LastUpdateDate != null));
}
obj.LastUpdateDate = Datetime.Now;
Mapper.map(objDTO,obj);
after mapping obj.LastUpdateDate will become null despite the condition I created.
happens for all members of the object.
Automapper 5.02
Are you positive LastUpdateDate is null? Datetime has a default value so if you're not expliciting setting it to null your condition won't catch it.
Try:
cfg.CreateMap<ObjectDTO, Object>()
.ForMember(dest => dest.LastUpdateDate, opt => opt.Condition(c => c.LastUpdateDate != null && c.LastUpdateDate != default(DateTime)));
Edit:
class Program
{
static void Main(string[] args)
{
Mapper.Initialize(cfg =>
{
cfg.CreateMap<ObjectDTO, Object>()
.ForMember(dest => dest.Number, opt => opt.Condition(src => src.Number.HasValue))
.ForMember(dest => dest.LastUpdateDate, opt => opt.Condition(src => src.LastUpdateDate.HasValue));
});
Mapper.AssertConfigurationIsValid();
var source = new ObjectDTO { LastUpdateDate = DateTime.Now };
var destination = new Object { Number = 10, LastUpdateDate = DateTime.Now.AddDays(-10) };
var result = Mapper.Map(source, destination);
}
}
public class ObjectDTO
{
public int? Number { get; set; }
public DateTime? LastUpdateDate { get; set; }
}
public class Object
{
public int? Number { get; set; }
public DateTime? LastUpdateDate { get; set; }
}
The condition is on the source object, not on the destination.
So with better naming for variables you are saying:
.ForMember(dest => dest.LastUpdateDate, opt => opt.Condition(src => src.LastUpdateDate != null));
So, what is in your objDTO?
I am trying to map object's of the same type which have a collection of child objects and am finding that Ignore() applied to properties on the child object seem to be umm... ignored!
Here's a unit test which demonstrates the problem.
class A
{
public int Id { get; set; }
public string Name { get; set; }
public ICollection<B> Children { get; set; }
}
class B
{
public int Id { get; set; }
public string Name { get; set; }
}
[TestClass]
public class UnitTest1
{
[TestInitialize()]
public void Initialize()
{
Mapper.CreateMap<A, A>()
.ForMember(dest => dest.Id, opt => opt.Ignore());
Mapper.CreateMap<B, B>()
.ForMember(dest => dest.Id, opt => opt.Ignore());
}
[TestMethod]
public void TestMethod1()
{
A src = new A { Id = 0, Name = "Source", Children = new List<B> { new B { Id = 0, Name = "Child Src" } } };
A dest = new A { Id = 1, Name = "Dest", Children = new List<B> { new B { Id = 11, Name = "Child Dest" } } };
Mapper.Map(src, dest);
}
After the Map call the A object's Id property is still 1, as expected, but child B object's Id property is changed from 11 to 0.
Why?
There are several bugs in AutoMapper 4.1.1.
First is about UseDestinationValue: https://github.com/AutoMapper/AutoMapper/issues/568
Second is about nested collections: https://github.com/AutoMapper/AutoMapper/issues/934
Horrifying! The workaround is to map your B instances directly:
Mapper.CreateMap<A, A>()
.ForMember(dest => dest.Id, opt => opt.Ignore())
.ForMember(dest => dest.Children, opt => opt.Ignore());
Mapper.CreateMap<B, B>()
.ForMember(dest => dest.Id, opt => opt.Condition((ResolutionContext src) => false));
and add additional mapping calls:
Mapper.Map(src, dest);
Mapper.Map(src.Children.First(), dest.Children.First()); //example!!!
You may call Mapper.Map in cycle:
for (int i = 0; i < src.Children.Count; i++)
{
var srcChild = src.Children[i];
var destChild = dest.Children[i];
Mapper.Map(srcChild, destChild);
}
This will make things work right.