C
C#

help

How to map Entity Framework entities containing circular references to DTOs?

Kky1e11/18/2023
When querying data with Entity Framework, the result data appears to contain circular references. (Using the example data from the attached screenshots) If I query a Sport and include its Leagues, the result is a Sport with list of Leagues, where each League is associated with a Sport, and that Sport is associated with a list of Leagues... you get the idea. With the screenshotted mapper classes, attempting to convert the Sport entity to a DTO causes the app to crash. Makes sense. If i remove one of the related DTOs from the other DTO's definition, the mapper has no problem, but this affects the flexibility I'd like to have. I would also like to avoid using AutoMapper or other third-party libraries. What is the solution to this? Is there something I can/should do with Entity Framework to avoid circular references in the query results? Or is there a way to set up mapper classes to handle this in a way that prevents redundant data from being mapped? (e.g. do not map the Sport inside League when the League was retrieved from its Sport parent).
No description
No description
SSaber11/18/2023
the obvious solution is to not have circluar references in your dtos
AAngius11/18/2023
Entities might need circular references to configure the relationships DTOs don't You can break the reference circle wherever you want Sport has a league, cool. League doesn't have to contain sport, though
Kky1e11/18/2023
not sure how you can assume i dont have any use for having Sport in the League DTO without knowing anything about the app. but im gonna guess the suggestion would be to create a separate DTO for that? i imagine that would get really messy. i dont recall having this issue with AutoMapper, which leads me to think that library handles this in some way, but could be misremembering since it was long ago
AAngius11/18/2023
So you get a League to the frontend, that League contains Sports. Sure, I can see that. List a League details and what sports are contained with it. If you want to check which Leagues a Sport is in, though, I'd do that in a different view/endpoint/whatever Instead of recursively and cyclically loading, seemingly, everything
Kky1e11/18/2023
it's a large scale app with ~100 entities and tons of relationships amongst them. i pulled these two for the example because they are the most basic, but there are tons of instances where this comes up. another example would be Player and Game. in some cases, the Player is being queried and the Player's games are included. in other cases, the Game is queried and needs to include the Players. this doesn't seem like anything atypical to me... can't help but think there's some way to manage this better than avoiding it entirely. even if the answer is to create multiple entity -> DTO mapper classes for a single entity
Mmg11/18/2023
I would either share DTOs and set the nested Player -> Game -> Players property to null, or have different DTOs
AAngius11/18/2023
Yeah, in those cases you have a PlayerDto with a reference to GameDto, and that one has no reference back to PlayerDto And in the other case, you have a GameDto with a reference to PlayerDto, but this one has no reference back to GameDto A separate set for each case They're supposed to represent the data you expect to get They're not necessarily meant to be reusable I'd even argue that they shouldn't be
Kky1e11/18/2023
i saw someone's solution posted online was to null out the circular references after querying the entity. seems janky i'll prob create separate DTOs if im not able to find any better approach. i appreciate your guys input
AAngius11/18/2023
Use records to save yourself some typing Ah, wait, you are lol I wonder why the explicit properties, though, instead of using the primary ctor
Kky1e11/18/2023
probably a skill issue šŸ˜‰
Mmg11/18/2023
I think I ended up doing this when I had to serialize some circular dependencies I was doing a lot of very wrong things along with that, but that in particular I don't think was too bad
JJP11/18/2023
Some methods to consider: 1) Separate routes per resource, make an extra request, but simplify your object model and limit the # of routes required. This is a slight perf hit because of the extra trip, but can simplify things massively. - Want a player and their games? Query GET /Players/:playerid, GET /Games?playerId=:playerid 2) As Ky1e suggested, route per permutation. If you truly have this scenario a lot, this can get big quick. 3) You truly have an insanely complicated app, with hundreds of required permutations from the frontend. Investigate if exposing a query language like GraphQL is worth the investment. Personally, I default to #1, and use #2 (creating specific routes for a specific frontend component, plucking exactly what I need) in cases where there is a lot of aggregation happening, or performance is critical.
Kky1e11/18/2023
i appreciate the input. i have considered looking closer at GraphQL because of many instances where various front-end views need similar, but slightly different, forms of some data (e.g. each view uses the same base entity but one view needs related entities a, b, c, while a different view needs related entities x, y, z) im not very knowledgeable about GraphQL. would using GraphQL eliminate my issue with circular references entirely (and thus resulting in my mapper classes working fine?), or would it eliminate my need for mapper classes, or is that more of an unrelated suggestion based on the app description?
JJP11/18/2023
GraphQL would be a pretty large restructure. Probably replacing most of what you have. Definitely a nuclear option, and one that would warrant research My personal solution is closer to #1, where I make most resources filterable based on the related entities. Extra trip, and a per-route complexity increase for filtering, but you cut down the number of routes a lot in my exp.
PPixxelKick11/18/2023
You need to use bespoke DTOs, don't try to keep re-using the same DTOs. Your DTOs should explicitly only have precisely the data you need to expose for that specific endpoint. If that means making a bespoke LeagueDTO for your sports endpoint, that is different from the one used in your League endpoints, so be it. Typically I try and avoid "oversharing" on my API endpoints.

Looking for more? Join the community!

Want results from more Discord servers?
Add your server
Recommended Posts
āœ… Typeorm doesnt get the name from entityI need that typeorm get the ```name: "noInfoMILeadsToDistribute"``` inside Entity, but it wants to gProcessing files as fast as possibleHi everyone! I have a question that Iā€™m sure you can help me with. Iā€™m making a library that needs tāœ… [SOLVED] Does the 3rd line of code hold memory as a reference or does it hold the actual value?ayooo, quick question. pretty simple. Book is a custom class just so you know.... ```csharp Book boRequestsHello, i have never done something that i will say before, how can i send a request to an API Url, gWhy is my grid on Line 28 not calling back to my other script called Grid?āœ… Visual Studio 2022 Failing to Create C# ProjectWhat's happening here?āœ… Help with creating shapes on a windows form appI have created a windows form app to display shapes on a bitmap, my circle function works fine but mNo inbuilt functionsHello, im a year 1 student so my knowledge is not that massive. So i have this task for university wSignalR initial connection takes way too long (logs included in comments)Hey there. So I have two versions of the same application, using essentially the same code. One of āœ… How to make DontDestroyOnLoad work for only single scene?Hello! I have a problem. In my game, when I am on my Main Menu Scene and trying to load Main Game ScUI is lagging while scrolling a listViewHi, I wanted to create an application that retrieves data from the API and displays it. I'm having tHow can i fix this error code?he's giving me an error code for private?Visual Studio 2022 ExtensionI'm working on a visual studio 2022 Extension. But as soon as i import it inside the visual studio 2āœ… ValidationContext in ASP.NETWhat does ObjectInstance and ObjectType mean? afaik 1) ValidationContext is basically on which claUpdated from 2021 to 2022 version of unity, getting NavMeshSurface related error.Hey y'all, I'm an absolute newbie trying to make a basic game and figured the unity tutorials would Cache not clearing, what am I missing?Does anyone know why this cache is not clearing? I am trying to implement simple rate limiting an aiCal (webcal://) does not doing a sync in outlook365I have my .net core app, and my app generates a link using iCal.NET nuget, and initially it generateDesign Pattern for mapping generic class type to implementationHey all, I'm working on an executor service that maps an executor record of a generic type to an exāœ… Blazor Tutorial (Todo List) Doesn't WorkHello guys, I'm new in Blazor. ```@page "/todo" <PageTitle>Todo</PageTitle> <h1>Todo (@todos.CountString AppendI have the following code: ``` blablabla.1 { row1.withCode row2.withCode row3.withCode row4.