C
C#3w ago
Rodonies

EF Core mapping to Viewmodels without duplicating viewmodels

//EF Core Entities
DogEntity {
public string Nickname;
public List<DogOwnerRelationEntity> Relationships;
}

DogOwnerRelationEntity {
public DogEntity Dog;
public OwnerEntity Owner;
public int RelationshipScore;
}

OwnerEntity {
public string Name;
public List<DogOwnerRelationEntity> Relationships;
}

//ViewModels
DogViewModel {
public string Nickname;
public List<DogOwnerRelationViewModel> Relationships;
}

DogOwnerRelationViewModel {
public DogViewModel Dog;
public OwnerViewModel Owner;
public int RelationshipScore;
}

OwnerViewModel {
public string Name;
public string PhoneNumber;
public List<DogOwnerRelationViewModel> Relationships;
}

//Extension methods
//this will end up running forever due to the circular nature of the many-to-many relationship, ignore this for now.
public static OwnerViewModel ToViewModel(this OwnerEntity ownerEntity) {
return new {
Name = ownerEntity.Name;
Relationships = [.. ownerEntity.Relationships.Select(static relationship => relationship.ToModel()]
}
}

public static DogOwnerRelationViewModel ToViewModel(this DogOwnerRelationEntity relationshipEntity) {
return new {
RelationshipScore = relationshipEntity.RelationshipScore;
Dog = relationshipEntity.Dog.ToViewModel()
Owner = relationshipEntity.Owner.ToViewModel()
}
}

public static DogViewModel ToViewModel(this DogEntity dogEntity) {
return new {
Nickname = dogEntity.Nickname;
Relationships = [.. ownerEntity.Relationships.Select(static relationship => relationship.ToModel()]
}
}

List<DogEntity> DogEntities = GetDogsFromDatabase()
List<DogViewModel> DogViewModels = [.. DogEntities.Select(dogEntity => dogEntity.ToViewModel())];
//EF Core Entities
DogEntity {
public string Nickname;
public List<DogOwnerRelationEntity> Relationships;
}

DogOwnerRelationEntity {
public DogEntity Dog;
public OwnerEntity Owner;
public int RelationshipScore;
}

OwnerEntity {
public string Name;
public List<DogOwnerRelationEntity> Relationships;
}

//ViewModels
DogViewModel {
public string Nickname;
public List<DogOwnerRelationViewModel> Relationships;
}

DogOwnerRelationViewModel {
public DogViewModel Dog;
public OwnerViewModel Owner;
public int RelationshipScore;
}

OwnerViewModel {
public string Name;
public string PhoneNumber;
public List<DogOwnerRelationViewModel> Relationships;
}

//Extension methods
//this will end up running forever due to the circular nature of the many-to-many relationship, ignore this for now.
public static OwnerViewModel ToViewModel(this OwnerEntity ownerEntity) {
return new {
Name = ownerEntity.Name;
Relationships = [.. ownerEntity.Relationships.Select(static relationship => relationship.ToModel()]
}
}

public static DogOwnerRelationViewModel ToViewModel(this DogOwnerRelationEntity relationshipEntity) {
return new {
RelationshipScore = relationshipEntity.RelationshipScore;
Dog = relationshipEntity.Dog.ToViewModel()
Owner = relationshipEntity.Owner.ToViewModel()
}
}

public static DogViewModel ToViewModel(this DogEntity dogEntity) {
return new {
Nickname = dogEntity.Nickname;
Relationships = [.. ownerEntity.Relationships.Select(static relationship => relationship.ToModel()]
}
}

List<DogEntity> DogEntities = GetDogsFromDatabase()
List<DogViewModel> DogViewModels = [.. DogEntities.Select(dogEntity => dogEntity.ToViewModel())];
4 Replies
Rodonies
RodoniesOP3w ago
Let's say I have 2 dogs nicknamed "Teddy" and "Biscuit" who both have 1 owner, "John" Ignoring the circular nature, this will create 2 separate Owner entities, one for each dog. When I show 2 windows for each dog, bind on the owner and change the owners PhoneNumber for "Teddy", the window for "Biscuit" will still show the old owner's phone number. My current method to avoid this is to get each Dog, each Relationship and each Owner separately, create the basic ViewModels (only strings/ints/etc, not other classes) and stitch these together afterwards. This becomes quite annoying/prone to errors considering the amount of classes/relationships I have in my real project. @Pope do you have any idea on how to approach this problem easier?
Angius
Angius2w ago
What data do you want to get? Dogs and their owners? Select that on the query level, that way there's not gonna be any circular issues
Rodonies
RodoniesOP2w ago
that's not the problem, it's about mapping the retrieved entities to viewmodels, it's creating a new Owner object twice
Angius
Angius2w ago
Ah, right

Did you find this page helpful?