Mapster
Mapster copied to clipboard
Error with cycle references
I have try a simple test with three classes to simulate a bidirectional navigation properties between to classes, using the same instance fot the same entities. The three classes are these:
[DataContract]
public class ClaseTest2
{
[DataMember(Order = 1)]
public ClaseTest3 Clase3 {get; set; }
}
[DataContract]
public class ClaseTest3
{
[DataMember(Order = 1)]
public ClaseTest2 Clase2 { get; set; }
}
[DataContract]
public class ClaseTest4
{
public ClaseTest4()
{
ClaseTest2 miClase2 = new ClaseTest2();
ClaseTest3 miClase3 = new ClaseTest3();
miClase2.Clase3 = miClase3;
miClase3.Clase2 = miClase2;
this.Clase2 = miClase2;
}
[DataMember(Order = 1)]
public ClaseTest2 Clase2;
}
I have also create my Class4DTO:
[DataContract] public class ClaseTest4DTO { [DataMember(Order = 1)] public ClaseTest2DTO Clase2; }
In the constructor of the class 4, that is which I want to adapt to the class 4 DTO, I ensure that I have only one instance of Class2 and Class3, and they are referenced one to each other in each case.
But I get an error of stackoverflow.
Stack overflow.
Repeat 19382 times:
--------------------------------
at DynamicClass.lambda_method7(System.Runtime.CompilerServices.Closure, GTS.Cmms.DemoGrpc.Service.Grpc.Comun.ClaseTest2)
--------------------------------
at DynamicClass.lambda_method6(System.Runtime.CompilerServices.Closure, System.Object)
at Mapster.TypeAdapter.Adapt[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Object, Mapster.TypeAdapterConfig)
at GTS.Cmms.DemoGrpc.Service.Grpc.AspCoreHost.FacturasService+<GetClase4DTOAsync>d__2.MoveNext()
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.__Canon ByRef)
at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Start[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.__Canon ByRef)
at GTS.Cmms.DemoGrpc.Service.Grpc.AspCoreHost.FacturasService.GetClase4DTOAsync(ProtoBuf.Grpc.CallContext)
at DynamicClass.lambda_method3(System.Runtime.CompilerServices.Closure, GTS.Cmms.DemoGrpc.Service.Grpc.AspCoreHost.FacturasService, ProtoBuf.Grpc.Internal.Empty, Grpc.Core.ServerCallContext)
If for example I don't assign the instance of class 3 to the property of the class2 in the constructor of the class4, it works. But then I lose the informaction that I would like to have.
In the documentation, it is used some example that uses a dbContext, I guess it is Entity Core, to map the result of the query:
using (MyDbContext context = new MyDbContext())
{
// Build a Select Expression from DTO
var destinations = context.Sources.ProjectToType<Destination>().ToList();
// Versus creating by hand:
var destinations = context.Sources.Select(c => new Destination {
Id = c.Id,
Name = c.Name,
Surname = c.Surname,
....
})
.ToList();
}
If the entities have bidirectional navigation properties and is not used the option of AsNoTracking() to don't use the same instances for the same entity, that it is the test that I did with the three classes above, then I would have the same problem of stack overflow.
Is it possible to map this kind of bidirectional navigation properties?
Thanks.
I have tried to use this code:
var miConfig = TypeAdapterConfig<ClaseTest4, ClaseTest4DTO>
.NewConfig()
.PreserveReference(true);
ClaseTest4 miClaseTest4 = new ClaseTest4();
ClaseTest4DTO miClase4DTO = miClaseTest4.Adapt<ClaseTest4DTO>();
But I have estill the same problem.
The only way that I don't get the problem is with MaxDepth(), but I have the problem with PreserveReference(), ShallowCopyForSameType() and AvoidInlineMapping().
But I would like to know why only works with MaxDepth and no the other options, because I would like to if there is some option that map all the graph and I don't have to set the max depth, because it would be different in each case (I mean, from different quieries from EF Core).
Thanks.
you dont pass config to Adapt method
I have tried too:
var miConfig = TypeAdapterConfig<ClaseTest4, ClaseTest4DTO>
.NewConfig()
.PreserveReference(true);
ClaseTest4 miClaseTest4 = new ClaseTest4();
ClaseTest4DTO miClase4DTO = miClaseTest4.Adapt<ClaseTest4DTO>(miConfig);
But I get an error that tells that can't convert miConfig from TypeAdapterSetter<Clase4, Clase4DTO> to TypeAdapterConfig.
How could I pass the config to the Adapt() method? In the documentation I don't see the example, also why it works if I use MaxDepth() but not PreserveReference? In any of both cases I pass the config to the Adapt() method.
Thanks.