LINQ requête pour un forum
-
06-09-2019 - |
Question
Je codage ce forum et depuis que je suis nouveau à LINQ je suis tombé sur ce problème lorsque l'utilisateur accède à la page principale. Je veux un tableau affichant une liste des forums comme celui-ci:
Forum --- Topics (count) --- Posts (count) --- LastPostUserId --- LastPostTime
Je les tables SQL suivantes:
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)
Merci ...
La solution
Pour afficher le nom de l'utilisateur si vous utilisez l'adhésion et que vous ne voulez pas inclure les aspnet_Users dans votre dbml:
...
LastPostUserId = posts.OrderByDescending(p=>p.PostId).Take(1).Select(p=> Membership.GetUser(p.UserId))
...
Un autre changement pour rendre votre échantillon posté un peu mieux est d'ajouter le OrderByDescending dans les postes variables: Ensuite, vous pouvez déposer les 4 fois OrderByDescending répété de la clause select:
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)
}
Ou encore plus propre:
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
}
Testez ce code quand il n'y a pas de derniers messages tho, je pense qu'il pourrait jeter une erreur si Take (1) est nulle ..
Autres conseils
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))
}
non testé ofcourse, mais essayez de démarrer à partir d'ici et de vérifier la requête SQL (s) il exécute et laissez-moi savoir si elle a besoin d'optimiser.
fait presque le tour (bien qu'il génère une SQL horrible -) ...)
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)
}
La dernière chose - j'ai une relation de « ForumPosts » table SQL 'Aspnet_Users et je voudrais afficher la colonne Aspnet_Users.UserName comme LastPostUserName ... Comment cela peut-il être fait? Et comment voulez-vous optimiser toute requête?