none
DTOs, serialization boundaries, automapper, EF RRS feed

  • Question

  • The best things I've found to read are these, but there are caveats to getting this working in a MAINTAINABLE way. (like must use .NET in all clients).

    So with out exposing the Entities to the client side I've got a number of DTOs that are suspiciously similar to the Entities...

    Great for Automapper as its pretty easy to map these as they all have properties with the same names.

    so good so far, but Im' interested in how you guys manage the recursive nature of some of the relationships in the system without getting stack overflows and/or serialization issues (but also keeping it simple/maintainable):

    eg: 

    House has door (property -> Door House.MainDoor{get;set;})

    door belongs to house (property -> House Door.BelongingHouse{get;set;})

    EF/automapper will use reflection to continuously find a 
    House1.MainDoor.BelongingHouse.MainDoor.BelongingHouse... where its just House1 and Door1, repeated over and over...

    Now you can use PreserveObjectReferences (as per) but this forces you to demand .NET on both sides of the wire and shared assemblies, which is no good here.

    So this was really helpful "dont panic labs My Battle with WCF serialization  in helping me to understand (a) I was having the same problems as someone and (b) in understanding that "this seems too hard, there must be a better way that is more maintainable".

    So I've come to the "assumed resolution" that EF -> Autmapper/custom mapping/or whatever tool -> DTO -> client objects is the best all around solution (even though its still very code heavy (or you need to find some EF 2 DTO like tools to remove that pain)) however I am still struggling with the following issues (yes all that was the preamble! sorry!)

    ------------------------

    so most of the DTOs are similar or identical to the EF entities, but we've strategically created boundaries around certain things in order to remove or reduce the "house->door" recursion (eg: organisation -> orders -> lines -> shipped line -> shipment -> order -> organisation -> orders -> lines... and so on)

    so "orders" DTO will only have "order - line"

    organisation only has "itself" mostly

    and so on... this has reduced our issues dramatically, but...

    --------------------------

    A)

    We are finding small bugs like this:

    if EF has proxys on this isn't an issue server side (because obviously the proxy makes the request "on demand" and if the mapping says to get that object it does get it) but when proxys/lazy loading is off we get weird bugs introduced when we have code like this:

    org = db.Organisation.Include("Orders");
    user = db.Users.Where(p=>p.orgid = org.orgid);user.LastOrder <- will be populated IF the users last order was with the Organisation, but if was with another organisation it will be null...

    if this is serialized then you get weird display issues clientside "now you see it now you don't"... are these things just "unit testing" and UAT things, or is there a better way to be catching these things earlier than that?

    ------------------------------

    B)

    Similarly to the "drawing careful lines" above, we wonder if there is somethign we are missing that will either make drawing these lines easier, or unnecessary perhaps.

    if we have lists of things that have other lists of things that also have the first things in them then both the seriaizer and automapper will frequently overflow because of the recursion if we aren't careful.

    So is there either an easy way to avoid this, or is there a pattern of unit testing that will help us to not hit this issue...?

    Or is this again "Unit and UAT" testing that needs to catch these things... (often our dev/dummy data is too simple and these are not getting caught until test (or worse in production!).

    Is this just experience of knowing what domain boundaries look like instinctively, or is there some other technique/pattern that will help us out?


    - sure I'm noJedi but that's no reason to stop trying to make stuff levitate! -


    • Edited by noJedi Tuesday, July 26, 2016 5:45 AM
    Tuesday, July 26, 2016 5:41 AM

Answers

  • Or... are we over complicating this completely and is the general (and I'm convinced "too easy and wont work for some obscure reason") solution to just remove all the "my parent" properties from the DTOs...

    so for example:

    Order -> lines

    just remove the "Line.ParentOrder" property...

    Surely it can't be that simple...? But if it is that simple, then is there an easy way to identify all these things, especially on a complex model (ie 100+ entities with lots of relationships) or do you just look for public <entity> name{get;set;} and flag them as potential issues...


    - sure I'm noJedi but that's no reason to stop trying to make stuff levitate! -


    • Edited by noJedi Tuesday, July 26, 2016 6:18 AM
    • Marked as answer by noJedi Wednesday, August 3, 2016 6:09 AM
    Tuesday, July 26, 2016 6:15 AM
  • and this: https://lostechies.com/jimmybogard/2011/02/09/autoprojecting-linq-queries/ 

    - sure I'm noJedi but that's no reason to stop trying to make stuff levitate! -

    • Marked as answer by noJedi Wednesday, August 3, 2016 7:29 AM
    Wednesday, August 3, 2016 7:29 AM

All replies

  • Or... are we over complicating this completely and is the general (and I'm convinced "too easy and wont work for some obscure reason") solution to just remove all the "my parent" properties from the DTOs...

    so for example:

    Order -> lines

    just remove the "Line.ParentOrder" property...

    Surely it can't be that simple...? But if it is that simple, then is there an easy way to identify all these things, especially on a complex model (ie 100+ entities with lots of relationships) or do you just look for public <entity> name{get;set;} and flag them as potential issues...


    - sure I'm noJedi but that's no reason to stop trying to make stuff levitate! -


    • Edited by noJedi Tuesday, July 26, 2016 6:18 AM
    • Marked as answer by noJedi Wednesday, August 3, 2016 6:09 AM
    Tuesday, July 26, 2016 6:15 AM
  • You can send as it XML string you do the XML not WCF taking the DTO and doing XML serialization, or you can send it as Json.
    Tuesday, July 26, 2016 9:40 PM
  • and this: https://lostechies.com/jimmybogard/2011/02/09/autoprojecting-linq-queries/ 

    - sure I'm noJedi but that's no reason to stop trying to make stuff levitate! -

    • Marked as answer by noJedi Wednesday, August 3, 2016 7:29 AM
    Wednesday, August 3, 2016 7:29 AM