【问题标题】:LINQ query for a forum论坛的 LINQ 查询
【发布时间】:2010-10-30 05:14:15
【问题描述】:

我正在为这个论坛编写代码,由于我是 LINQ 新手,所以当用户点击主页时我遇到了这个问题。我想要一个显示论坛列表的表格,如下所示:

Forum  --- Topics (count) --- Posts (count) --- LastPostUserId --- LastPostTime

我有以下 SQL 表:

Forums:
ForumId (int32),
Title (string),
Description (string)

ForumThreads:
ThreadId (int32),
ForumId (int32),
UserId (guid),
Subject (string),
Views (int32),
CreateDate (DateTime)

ForumPosts:
PostId (int32),
ThreadId (int32),
UserId (guid),
Post (string),
CreateDate (datetime)

谢谢...

【问题讨论】:

    标签: c# sql linq entity-framework linq-to-entities


    【解决方案1】:

    如果您使用会员资格并且不想在 dbml 中包含 aspnet_Users,则用于显示用户名:

    ...
    LastPostUserId = posts.OrderByDescending(p=>p.PostId).Take(1).Select(p=> Membership.GetUser(p.UserId))
    ...
    

    另一个使您发布的示例更好一点的更改是在 posts 变量中添加 orderbydescending: 然后您可以从 select 子句中删除 4 次重复的 OrderByDescending:

    from forum in Forums
    let posts = ForumPosts.Where(p => p.ForumThreads.ForumId.Equals(forum.ForumId)).OrderByDescending(p=>p.PostId)
    select new
    {
        Forum = forum.Title,
        Description = forum.Description,
        Topics = forum.ForumThreads.Count(),
        Posts = posts.Count(),
        LastPostId = posts.Take(1).Select(p=>p.PostId),
        LastPostThreadId = posts.Take(1).Select(p=>p.ThreadId),
        LastPostUserId = posts.Take(1).Select(p=>p.UserId),
        LastPostTime = posts.Take(1).Select(p=>p.CreateDate)
    }
    

    甚至更干净:

    from forum in Forums
    let posts = ForumPosts.Where(p => p.ForumThreads.ForumId.Equals(forum.ForumId))
    let lastPost = posts.OrderByDescending(p=>p.PostId).Take(1)
    select new
    {
        Forum = forum.Title,
        Description = forum.Description,
        Topics = forum.ForumThreads.Count(),
        Posts = posts.Count(),
        LastPostId = lastPost.PostId,
        LastPostThreadId = lastPost.ThreadId,
        LastPostUserId = lastPost.UserId,
        LastPostUserName = Membership.GetUser(lastPost.UserId),
        LastPostTime = lastPost.CreateDate
    }
    

    在没有最后一篇文章的情况下测试此代码,我认为如果 Take(1) 为空,它可能会引发错误..

    【讨论】:

    • Take(1) 为空时不会抛出错误。但是,似乎不可能将变量声明为 LastPostThreadId = lastPost.ThreadId - 我必须使用 .Select() 吗?另一件事.. 是否可以将值返回为强类型而不是 IOrderedQueryable 等等?
    • 啊,是的,那是因为 Take(1) 也可以是 Take(100),所以系统不知道您正在返回单个 ForumPost。这就是为什么你应该使用 .FirstOrDefault() 而不是 .Take(1)。这将让您使用 lastPost.CreateDate 并将其作为 DateTime 而不是 IOrderedQueryable. 返回
    • 无论如何你都必须检查 null 。最简单的方法是:LastPostTime = (lastPost != null ? lastPost.CreateDate : null)
    【解决方案2】:

    这几乎可以解决问题(尽管它会生成一些可怕的 SQL ;-)...)

    from forum in Forums
    let posts = ForumPosts.Where(p => p.ForumThreads.ForumId.Equals(forum.ForumId))
    select new
    {
        Forum = forum.Title,
        Description = forum.Description,
        Topics = forum.ForumThreads.Count(),
        Posts = posts.Count(),
        LastPostId = posts.OrderByDescending(p=>p.PostId).Take(1).Select(p=>p.PostId),
        LastPostThreadId = posts.OrderByDescending(p=>p.PostId).Take(1).Select(p=>p.ThreadId),
        LastPostUserId = posts.OrderByDescending(p=>p.PostId).Take(1).Select(p=>p.UserId),
        LastPostTime = posts.OrderByDescending(p=>p.PostId).Take(1).Select(p=>p.CreateDate)
    }
    

    最后一件事 - 我有一个从 SQL 表 'ForumPosts' 到 'Aspnet_Users' 的关系,我想将 Aspnet_Users.UserName 列显示为 LastPostUserName... 怎么办?您将如何优化整个查询?

    【讨论】:

    • 将 Aspnet_Users 添加到您的 dbml 和 p.aspnet_user.Name 应该可以正常工作,不是吗?
    • 为了优化查询,你能复制粘贴生成的sql吗?
    【解决方案3】:
    from forum in forums
    from posts in db.ForumPosts.Where(p => p.Thread.ForumId.Equals(forum.ForumId))
    select new
    {
    Forum = forum.Title, 
    Topics = forum.ForumThreads.Count(),
    Posts = posts.Count(),
    LastPostBy = posts.OrderByDescending(p => p.CreateDate).FirstOrDefault(p => p.UserId),
    LastPostTime= posts.Max(p => p.CreateDate))
    }
    

    当然未经测试,但尝试从这里开始检查它执行的 SQL 查询,如果需要优化,请告诉我。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-07
      • 2023-04-09
      相关资源
      最近更新 更多