EF核心Linq查询中的表连接
我目前正在尝试使用EF Core制作一个Web Api,但是在连接我已经组装好的表时遇到了一些问题。我正在使用以下数据库关系图: 我目前从API中获取的数据如下所示:EF核心Linq查询中的表连接,linq,entity-framework-core,asp.net-core-webapi,linq-query-syntax,Linq,Entity Framework Core,Asp.net Core Webapi,Linq Query Syntax,我目前正在尝试使用EF Core制作一个Web Api,但是在连接我已经组装好的表时遇到了一些问题。我正在使用以下数据库关系图: 我目前从API中获取的数据如下所示: [ { "postId":1, "postDate":"2018-10-21T21:56:43.9838536", "content":"First entry in posts!", "user":{ "userId":1,
[
{
"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":[
]
}
]
正如你所看到的,它最有效,我这里的问题是评论中的空值,我希望能够让用户也退出。但由于某种原因,我不能
我当前的查询如下所示(我使用DTO清理生成的JSON):
如果我使用SQL,我会将用户加入到“评论”中,但我做不到,所以我尝试了一个类似的ish解决方案,我认为这是可行的
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
};
然而,尽管此查询确实执行,但结果与我编写的第一个查询相同,问题是用户没有加入到注释中
TLDR;我可以将用户加入到帖子中,也可以将评论加入到帖子中,但我无法将用户绑定到评论中
我希望你能帮助我,提前谢谢:)
编辑:这是我的模型
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; }
}
公共类注释
{
public int CommentId{get;set;}
public DateTime PostDate{get;set;}
公共字符串内容{get;set;}
公共用户{get;set;}
公共Post Post{get;set;}
}
公共类用户
{
public int UserId{get;set;}
公共日期时间创建日期{get;set;}
公共字符串名称{get;set;}
公共ICollection Posts{get;set;}
公共ICollection注释{get;set;}
}
公营职位
{
公共int PostId{get;set;}
public DateTime PostDate{get;set;}
公共字符串内容{get;set;}
公共用户{get;set;}
公共ICollection注释{get;set;}
}
要获取带有评论的帖子(以及每个评论的用户)和帖子用户,只需使用.Include()
如果不想引入第三方库,如AutoMapper
,可以创建convertPostToToTo
函数并使用
res.Select(p=>convertPostToDto(p))
要将
res
转换为结果不要加入
,请使用导航属性。并使用AutoMapper,这样您就可以在一行代码中将实体类投影到DTO类。当前代码触发客户端评估,因为CommentDTO.CommentToDTO()
无法转换为SQL。您可以发布模型吗?正如@Gert所提到的,您应该真正使用导航属性。奇怪的是,你似乎有他们,但使用他们加入。但是这里的user
变量在上下文中加入用户。post.user.UserId上的用户等于user。UserId
与post.user
相同。如果我们继续,post
应该有ICollecton注释
,Comment
应该有User用户
,所以你应该能够通过选择
s(投影)来产生结果。我现在已经发布了模型。我有导航属性,是的,但我不确定如何正确利用它们,因为我还没有找到任何与我的数据库结构类似的示例,我尝试只使用包含进行查询,但它给了我太多的数据。示例:post+评论+评论用户+用户评论和用户帖子。@GertArnold我已经看过很多AutoMapper的建议,如果我做的是专业工作,我可能会使用它,因为它比手动操作快。但我这么做是为了好玩,因为我想知道这些东西是如何工作的:)不过还是谢谢你的建议!AutoMapper也很有趣:)但我明白你的意思。快乐编码!妈的,我根本没想过要那样做,现在我觉得自己是个非常愚蠢的人。我会试试看它对我是否有用:)除了最后的建议外,一切都好。永远不要创建函数并按建议使用它-这会导致客户评估,这应该避免。@IvanStoev非常感谢。我并没有意识到在数据库中将POST转换为dto是可能的。稍后我会尝试,如果我能确认所有转换都可以在数据库上完成,我会更新我的anwser。当然,不是在数据库中,而是在具体化查询结果时(它作为DbDataReader
出现,需要转换为对象)。但是使用可发现的投影允许EF创建必要的SQLSELECT
s并避免创建(和跟踪)中间实体对象。基本上,AutoMapperMap
和ProjectTo
之间的区别是:)无论如何,欢迎您。
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; }
}
var res = this._dbContext.Posts
.Include(p => p.User)
.Include(p => p.Comments)
.ThenInclude(c => c.User)
.ToList();