EF核心Linq查询中的表连接

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,

我目前正在尝试使用EF Core制作一个Web Api,但是在连接我已经组装好的表时遇到了一些问题。我正在使用以下数据库关系图:

我目前从API中获取的数据如下所示:

[  
   {  
      "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创建必要的SQL
SELECT
s并避免创建(和跟踪)中间实体对象。基本上,AutoMapper
Map
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();