C
C#2y ago
Thinker

Turn recursive entities into model [Answered]

I have two db entities like this:
public sealed class TodoListEntity {
public Guid Id { get; set; }
public ICollection<TodoItemEntity> Items { get; set; } = null!;
}
public sealed class TodoListEntity {
public Guid Id { get; set; }
public ICollection<TodoItemEntity> Items { get; set; } = null!;
}
public sealed class TodoItemEntity {
public Guid Id { get; set; }
// Other data

public Guid ListId { get; set; }
public TodoListEntity List { get; set; } = null!;
}
public sealed class TodoItemEntity {
public Guid Id { get; set; }
// Other data

public Guid ListId { get; set; }
public TodoListEntity List { get; set; } = null!;
}
I wanna turn this into a model/DTO, so I have these extensions
public static TodoList ToModel(this TodoListEntity entity) =>
new(entity.Id, entity.Items.Select(ToModel).ToArray());
public static TodoItem ToModel(this TodoItemEntity entity) =>
new(entity.Id, /* Other data */, entity.List.ToModel());
public static TodoList ToModel(this TodoListEntity entity) =>
new(entity.Id, entity.Items.Select(ToModel).ToArray());
public static TodoItem ToModel(this TodoItemEntity entity) =>
new(entity.Id, /* Other data */, entity.List.ToModel());
This however causes a stack overflow because ToModel(TodoListEntity) calls ToModel(TodoItemEntity) and so on which causes unbound recursion. What would the simplest way to fix this be? I somehow have to keep a single list which I can pass to all items inside it.
2 Replies
Thinker
Thinker2y ago
And I know it's not "recursive" entities but it's entities with backrefs Okay nvm I think I figured it out using this
public static TodoList ToModel(this TodoListEntity entity) {
List<TodoItem> items = new();
TodoList list = new(entity.Id, items);

foreach (var item in entity.Items) {
items.Add(ToModelShallow(item, list));
}

return list;
}
private static TodoItem ToModelShallow(TodoItemEntity entity, TodoList list) =>
new(entity.Id, /* Other data */, list);
public static TodoItem ToModel(this TodoItemEntity entity) =>
entity.List.ToModel().Items.First(e => e.Id == entity.Id);
public static TodoList ToModel(this TodoListEntity entity) {
List<TodoItem> items = new();
TodoList list = new(entity.Id, items);

foreach (var item in entity.Items) {
items.Add(ToModelShallow(item, list));
}

return list;
}
private static TodoItem ToModelShallow(TodoItemEntity entity, TodoList list) =>
new(entity.Id, /* Other data */, list);
public static TodoItem ToModel(this TodoItemEntity entity) =>
entity.List.ToModel().Items.First(e => e.Id == entity.Id);
Accord
Accord2y ago
✅ This post has been marked as answered!