I'm currently trying to make a Web Api with EF Core, and i'm running into some problems joining the tables i've got together. I'm working with the following Database Diagram:
And the data i'm currently getting back from my API looks this this:
[
{
"postId":1,
"postDate":"2018-10-21T21:56:43.9838536",
"content":"First entry in posts!",
"user":{
"userId":1,
"creationDate":"2018-10-21T21:56:36.3539549",
"name":"Hansel"
},
"comments":[
{
"commentId":1,
"postDate":"0001-01-01T00:00:00",
"content":"Nice!",
"user":null
},
{
"commentId":2,
"postDate":"0001-01-01T00:00:00",
"content":"Cool, here's another comment",
"user":null
},
{
"commentId":3,
"postDate":"0001-01-01T00:00:00",
"content":"and the last one for the night",
"user":null
}
]
},
{
"postId":2,
"postDate":"2018-10-22T21:56:44.0650102",
"content":"Its good to see that its working!",
"user":{
"userId":2,
"creationDate":"2018-10-16T21:56:36.4585213",
"name":"Chris"
},
"comments":[
]
}
]
As you can see, its aalmost working, my issue here is the null values in the comments, i want to be able to get the users out as well. But for some reason i cant.
my current query looks like this (i'm using DTO's to clean up the JSON generated):
var result = from post in context.Posts
join user in context.Users
on post.User.UserId equals user.UserId
join comment in context.Comments
on post.PostId equals comment.Post.PostId into comments
select new PostDTO
{
Content = post.Content,
PostDate = post.PostDate,
User = UserDTO.UserToDTO(user),
Comments = CommentDTO.CommentToDTO(comments.ToList()),
PostId = post.PostId
};
If i was working with SQL i'd join the users onto 'comments', but i cant, so i've tried a similar-ish solution, which i thought would work.
var result = from post in context.Posts
join user in context.Users on post.User.UserId equals user.UserId
join comment in
(from u in context.Users
join c in context.Comments
on u.UserId equals c.User.UserId select c)
on post.PostId equals comment.Post.PostId into comments
select new PostDTO
{
Content = post.Content,
PostDate = post.PostDate,
User = UserDTO.UserToDTO(user),
Comments = CommentDTO.CommentToDTO(comments.ToList()),
PostId = post.PostId
};
However, while this query does execute the results are the same as the first query i wrote, the issue being that user isnt joined onto comment
TLDR; I can join User to post, and comment to post, but i cant bind user to comment
I hope you will be able to help me, thanks in advance :)
Edit: Here's my models
public class Comment
{
public int CommentId { get; set; }
public DateTime PostDate { get; set; }
public string Content { get; set; }
public User User { get; set; }
public Post Post { get; set; }
}
public class User
{
public int UserId { get; set; }
public DateTime CreationDate { get; set; }
public string Name{ get; set; }
public ICollection<Post> Posts { get; set; }
public ICollection<Comment> Comments { get; set; }
}
public class Post
{
public int PostId { get; set; }
public DateTime PostDate { get; set; }
public string Content { get; set; }
public User User { get; set; }
public ICollection<Comment> Comments { get; set; }
}
join
, use navigation properties. And use AutoMapper, so you can project the entity classes to DTO classes in one line of code. The current code triggers client-side evaluation, becauseCommentDTO.CommentToDTO()
can't be translated into SQL. – Septimaluser
variable herejoin user in context.Users on post.User.UserId equals user.UserId
is the same aspost.User
. If we continue,post
should haveICollecton<Comment> Comments
andComment
should haveUser User
, so you should really be able to produce the result with justselect
s (projections). – Airdry