Is AutoMapper always create duplicates?

62 views
Skip to first unread message

vlad.mi...@gmail.com

unread,
Dec 15, 2015, 2:08:17 AM12/15/15
to AutoMapper-users
Hello!

I have two classes:

    public class Element
    {
        public Item Item { get; set; }
    }

    public class Item
    {
        public Element Element { get; set; }
    }

And I have DTO with same structure for this classes.
This method creates source data for mapping:

  static Element[] CreateElements()
  {
    var element2 = new Element();
    return new[]
    {
      new Element(new ParentItem(element2)),
      element2,
      new Element()
    };
  }
 
Then I configuring mapping and map elements:

    Mapper.CreateMap<Element, ElementDto>();
    Mapper.CreateMap<Item, ItemDto>();

    var elements = CreateElements();

    var mappedElements = elements
        .Select(_ => Mapper.Map(_, typeof(Element), typeof(ElementDto)))
        .OfType<ElementDto>()
        .ToArray();

After I check result of mapping:

    foreach (var element in mappedElements)
    {
        Console.WriteLine(mappedElements.Any(e => e?.Item?.Element == element));
    }

This code shows "False" three times.
It follows that the "element2" from "CreateElements" was created two copies.

As I need to configure the mapping to duplicate is not created? Is it possible?

Jimmy Bogard

unread,
Dec 15, 2015, 10:10:04 AM12/15/15
to automapper-users
Try not to have bidirectional relationships in your DTOs. It makes things much, much more difficult to manage and understand. That's my first suggestion.

--
You received this message because you are subscribed to the Google Groups "AutoMapper-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to automapper-use...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

vlad.mi...@gmail.com

unread,
Dec 16, 2015, 3:07:25 AM12/16/15
to AutoMapper-users, vlad.mi...@gmail.com
it has already happened :)
Can automapper set links to already created elements or not?

вторник, 15 декабря 2015 г., 10:08:17 UTC+3 пользователь vlad.mi...@gmail.com написал:

Jimmy Bogard

unread,
Dec 16, 2015, 7:39:55 AM12/16/15
to automapp...@googlegroups.com
Yes, it can. It uses equality to determine if an object has been mapped before. But it's not perfect, so the simple scenario you laid out below is already covered by tests but I'd need to see a fuller reproduction case to see what's wrong.

Sent from my iPad
--

vlad.mi...@gmail.com

unread,
Dec 16, 2015, 8:09:10 AM12/16/15
to AutoMapper-users
In this scenario AutoMapper didn't work as I expect.
In my example AutoMapper create 4 objects of type ElementDto. Three when copy flat list of elements and another one when copying element.Item.Element.
How to configure AutoMapper that it did not create a copy for element.Item.Element? In this case the for-loop in my example must returns "false true false".

среда, 16 декабря 2015 г., 15:39:55 UTC+3 пользователь Jimmy Bogard написал:

vlad.mi...@gmail.com

unread,
Dec 16, 2015, 8:34:22 AM12/16/15
to AutoMapper-users, vlad.mi...@gmail.com
I'll add all my code:

class Program
   
{
       
static void Main(string[] args)
       
{

           
Mapper.CreateMap<Element, ElementDto>();
           
Mapper.CreateMap<Item, ItemDto>();

           
var elements = CreateElements();

           
var mappedElements = elements
               
.Select(_ => Mapper.Map(_, typeof(Element), typeof(ElementDto)))
               
.OfType<ElementDto>()
               
.ToArray();


           
foreach (var element in elements)
           
{
               
Console.WriteLine(elements.Any(e => e?.Item?.Element == element));
           
}

           
Console.WriteLine("***");


           
foreach (var element in mappedElements)
           
{
               
Console.WriteLine(mappedElements.Any(e => e?.Item?.Element == element));
           
}
       
}


       
static Element[] CreateElements()

       
{
           
var element2 = new Element();
           
return new[]
           
{

               
new Element(new Item(element2)),
                element2
,
               
new Element()
           
};
       
}
   
}

   
public class Element
   
{
       
public Element (Item item)
       
{
           
Item = item;
       
}

       
public Element()
           
: this(null)

       
{
       
}
     
       
public Item Item { get; set; }
   
}
   
   
public class Item
   
{

       
public Item(Element parent)
       
{
           
Element = parent;
       
}

       
public Item()
           
: this(null)

       
{
       
}
       
       
public Element Element { get; set; }
   
}

   
   
public class ElementDto
   
{
       
public ItemDto Item { get; set; }
   
}

   
public class ItemDto
   
{
       
public ElementDto Element { get; set; }
   
}














The same cycle produces different results for elements and mappedElements

 

Jimmy Bogard

unread,
Dec 17, 2015, 5:06:45 PM12/17/15
to automapper-users, vlad.mi...@gmail.com
Yeah I get the same results too.

I gotta be totally honest - I wouldn't model your DTOs this way. You have no equality operators, so you have to rely solely on reference equality, making it quite hard to track and duplicate a graph from one point to another.

Don't do circular graphs in your DTOs.

Reply all
Reply to author
Forward
0 new messages