2009-05-31 14 views
3

私はこのフォーラムをコーディングしています。私はLINQを初めて使ったので、ユーザーがメインページにヒットしたときにこの問題に遭遇しました。私はこのようなフォーラムの一覧を表示するテーブルが欲しい:フォーラムの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) 

はofcourseのテストされていない

答えて

1

:あなたの投稿サンプルは少し良くするために

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

もう一つの変化は、中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) 
} 

あるいはクリーナー:

何の最近の投稿はありません

テストこのコードはカントー、私は

+0

Take(1)がnullの場合、エラーをスローしません。しかし、それはLastPostThreadId = lastPost.ThreadIdとして変数を宣言することはできないようです - 私は.Select()を使用する必要がありますか? IOrderedQueryableの代わりに強く型付けされた値を返すことは可能ですかなど? – Morten

+0

ああ、それはTake(1)もTake(100)である可能性があるので、システムはあなたが単一のForumPostを返していることを知らないからです。そのため、.Take(1)の代わりに.FirstOrDefault()を使用する必要があります。これにより、lastPost.CreateDateを使用できるようになり、IOrderedQueryable ではなくDateTimeとして返されます。 –

+0

とにかくnullをチェックする必要があります。最も簡単な方法は次のとおりです。 LastPostTime =(lastPost!= null?lastPost.CreateDate:null) –

2
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クエリをチェックし、最適化が必要かどうかを教えてください。

0

これはほとんどのトリック(それはいくつかの恐ろしい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) 
} 

最後の事は - 私は「Aspnet_Users」にSQLテーブル「ForumPosts」から関係を持っていると私だろうLastPostUserNameとして列Aspnet_Users.UserNameを表示するように...どのように行うことができますか?クエリ全体をどのように最適化しますか?あなたがメンバーシップを使用して、あなたのDBMLでaspnet_Users含めたくない場合は、ユーザーの名前を表示するための

+0

..テイク(1)がnullの場合、それはエラーをスローかもしれないと思うだけで、動作するはずですあなたのDBMLとp.aspnet_user.NameにAspnet_Usersを追加いいえ? –

+0

クエリを最適化するために、生成されたSQLを貼り付けてコピーできますか? –