Reputation: 860
I am a model relations as below
Post Model
public class Post : BaseEntity
{
public int Id { get; set; }
public string Content { get; set; }
public string Image { get; set; }
public virtual User User { get; set; }
[Column( "user_id" )] public string UserId { get; set; }
public virtual List< Comment > Comments { get; set; }
}
User Model
public class User : IdentityUser
{
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
[Column( "created_at", Order = 254 )] public DateTime CreatedAt { get; set; }
[Column( "updated_at", Order = 255 )] public DateTime UpdatedAt { get; set; }
public virtual ICollection< Post > Posts { get; set; }
public virtual ICollection< Comment > Comments { get; set; }
}
Comment Model
public class Comment : BaseEntity
{
public int Id { get; set; }
public string Content { get; set; }
public virtual User User { get; set; }
[Column( "user_id" )] public string UserId { get; set; }
public virtual Post Post { get; set; }
[Column( "post_id" )] public int PostId { get; set; }
}
And when I do this
public IEnumerable< Post > GetAllPosts()
{
return dbContext.Posts
.Include( post => post.User )
.ThenInclude( post => post.Comments )
.ToList();
}
I get multiple depths of data. I only need one level of child
This is my output for just a post. The data is repeating itself.
[
{
"id": 5,
"content": "This post is about fires going on in NSW",
"image": null,
"user": {
"firstName": "Bikram",
"middleName": null,
"lastName": "Bhandari",
"createdAt": "0001-01-01T00:00:00",
"updatedAt": "0001-01-01T00:00:00",
"posts": [], --I don't want this
"comments": [ -- Unwanted
{
"id": 7,
"content": "So sad to see this",
"userId": "052b4889-431f-48d2-b673-5835166c03ee",
"postId": 5,
"createdAt": "0001-01-01T00:00:00",
"updatedAt": "0001-01-01T00:00:00"
},
{
"id": 8,
"content": "Let's hope for a rain",
"userId": "052b4889-431f-48d2-b673-5835166c03ee",
"postId": 5,
"createdAt": "0001-01-01T00:00:00",
"updatedAt": "0001-01-01T00:00:00"
}
],
"id": "052b4889-431f-48d2-b673-5835166c03ee",
"userName": "[email protected]",
"normalizedUserName": "[email protected]",
"email": "[email protected]",
"normalizedEmail": "[email protected]",
"emailConfirmed": false,
"passwordHash": "AQAAAAEAACcQAAAAEHBFj2Woq4/JhqyPWtaXt2xjL4+ML9XQR24pYJsvUAaAKWr/Pg4NgQ2S/O1h8fkerg==",
"securityStamp": "XVNJKDOYMMT6SP2LLBUNHRKWGT3NZB4X",
"concurrencyStamp": "2658eced-edd7-4458-b9e2-a010b46e3f37",
"phoneNumber": null,
"phoneNumberConfirmed": false,
"twoFactorEnabled": false,
"lockoutEnd": null,
"lockoutEnabled": true,
"accessFailedCount": 0
},
"userId": "052b4889-431f-48d2-b673-5835166c03ee",
"comments": [
{
"id": 7,
"content": "So sad to see this",
"user": { --Not wanted
"firstName": "Bikram",
"middleName": null,
"lastName": "Bhandari",
"createdAt": "0001-01-01T00:00:00",
"updatedAt": "0001-01-01T00:00:00",
"posts": [],
"comments": [ --Not wanted
{
"id": 8,
"content": "Let's hope for a rain",
"userId": "052b4889-431f-48d2-b673-5835166c03ee",
"postId": 5,
"createdAt": "0001-01-01T00:00:00",
"updatedAt": "0001-01-01T00:00:00"
}
],
"id": "052b4889-431f-48d2-b673-5835166c03ee",
"userName": "[email protected]",
"normalizedUserName": "[email protected]",
"email": "[email protected]",
"normalizedEmail": "[email protected]",
"emailConfirmed": false,
"passwordHash": "AQAAAAEAACcQAAAAEHBFj2Woq4/JhqyPWtaXt2xjL4+ML9XQR24pYJsvUAaAKWr/Pg4NgQ2S/O1h8fkerg==",
"securityStamp": "XVNJKDOYMMT6SP2LLBUNHRKWGT3NZB4X",
"concurrencyStamp": "2658eced-edd7-4458-b9e2-a010b46e3f37",
"phoneNumber": null,
"phoneNumberConfirmed": false,
"twoFactorEnabled": false,
"lockoutEnd": null,
"lockoutEnabled": true,
"accessFailedCount": 0
},
"userId": "052b4889-431f-48d2-b673-5835166c03ee",
"postId": 5,
"createdAt": "0001-01-01T00:00:00",
"updatedAt": "0001-01-01T00:00:00"
},
{ --Not wanted
"id": 8,
"content": "Let's hope for a rain",
"user": {
"firstName": "Bikram",
"middleName": null,
"lastName": "Bhandari",
"createdAt": "0001-01-01T00:00:00",
"updatedAt": "0001-01-01T00:00:00",
"posts": [],
"comments": [
{
"id": 7,
"content": "So sad to see this",
"userId": "052b4889-431f-48d2-b673-5835166c03ee",
"postId": 5,
"createdAt": "0001-01-01T00:00:00",
"updatedAt": "0001-01-01T00:00:00"
}
],
"id": "052b4889-431f-48d2-b673-5835166c03ee",
"userName": "[email protected]",
"normalizedUserName": "[email protected]",
"email": "[email protected]",
"normalizedEmail": "[email protected]",
"emailConfirmed": false,
"passwordHash": "AQAAAAEAACcQAAAAEHBFj2Woq4/JhqyPWtaXt2xjL4+ML9XQR24pYJsvUAaAKWr/Pg4NgQ2S/O1h8fkerg==",
"securityStamp": "XVNJKDOYMMT6SP2LLBUNHRKWGT3NZB4X",
"concurrencyStamp": "2658eced-edd7-4458-b9e2-a010b46e3f37",
"phoneNumber": null,
"phoneNumberConfirmed": false,
"twoFactorEnabled": false,
"lockoutEnd": null,
"lockoutEnabled": true,
"accessFailedCount": 0
},
"userId": "052b4889-431f-48d2-b673-5835166c03ee",
"postId": 5,
"createdAt": "0001-01-01T00:00:00",
"updatedAt": "0001-01-01T00:00:00"
}
],
"createdAt": "0001-01-01T00:00:00",
"updatedAt": "0001-01-01T00:00:00"
}
]
If you see above you can see that the data are repeating itself. What am I doing wrong to retrieve all the posts and the user associated with the post and all the comments of a post? Can anybody suggest how should I define my model relations to better retrieve my data? I want to retrieve all the posts and comments from user's perspective too. And in the comments model, I want to know which post the comment belongs to and who is the owner of the comment too. Thank you in advance.
Upvotes: 0
Views: 104
Reputation: 89091
The Change Tracker will fix-up releationships as it loads entities. So if you load a Post's comments, and you have already loaded the User for some of those comments, the Navigation Property between User and Comments will be set.
If change tracking is enabled, then when loading an entity, EF Core will automatically set the navigation properties of the newly-loaded entitiy to refer to any entities already loaded, and set the navigation properties of the already-loaded entities to refer to the newly-loaded entity.
Loading Related Data - EF Core: Explicit Loading
Disable Change Tracking on the DbContext to prevent this behavior,
public IList< Post > GetAllPosts()
{
return dbContext.Posts.AsNoTracking()
.Include( post => post.User )
.ThenInclude( post => post.Comments )
.ToList();
}
And return IList<T>
, not IEnumerable<T>
, otherwise your caller won't know whether this is a streaming result, and might defensively load the result into a list.
Alternatively specify the shape of the document in your JSON serializer.
Upvotes: 2