asp.net врезал комментарии?
Я работаю над созданием блога в ASP.net 4.0 и SQL Server 2008 и хотел бы узнать, как создать систему многопоточных комментариев. Под резьбой я подразумеваю, что у каждого комментария будет ссылка для ответа, а комментарии имеют отступ под комментарием, на который он является ответом. Таким образом, вы можете либо ответить на саму статью, либо ответить на любой из комментариев.
Это очень часто встречается на форумах и блогах, но я не могу найти ни одной статьи, которая бы объясняла и показывала пример кода о том, как это делается.
Вот то, что я создал, но он работает только на одном уровне глубины. Я хотел бы сделать его рекурсивным, чтобы не было ограничений по уровню глубины. Как я могу это сделать? Любые советы, статьи с примерами кода были бы потрясающими!
Комментарии дБ Таблица
commentId
parentId
postId
date
author
authorEmail
authorURL
authorIP
content
IsApproved
Разметка ASP.NET:
<asp:ListView ID="ListView1" runat="server" onitemdatabound="ListView1_ItemDataBound">
<ItemTemplate>
<div class="commentwrap">
<div class="commentsTitleArea">
<span class="commentCounter"><%# Convert.ToInt32(Container.DisplayIndex) + 1%>. </span> <img src="../images/decoy-icon-16px.png" alt="Comment by..." title="Comment by..." class="blogCommentIcon" /><a href='<%# Eval("AuthorUrl")%>' target="_blank" rel="nofollow"><%# " " + Eval("Author")%></a> <%# Eval("Date")%></div>
<div class="commentText">
<%# Eval("Content") %>
<div><span class="btnCommentReply"><a href='<%# "article.aspx?article=" + Request.QueryString["article"] + "&cid=" + Eval("commentId") + "#comment" %>'>REPLY</a></span></div>
</div>
<asp:ListView ID="ListView2" runat="server">
<ItemTemplate>
<div class="commentwrap commentNest">
<div class="commentsTitleArea">
<span class="commentCounter"><%# Convert.ToInt32(Container.DisplayIndex) + 1%>. </span> <img src="../images/decoy-icon-16px.png" alt="Comment by..." title="Comment by..." class="blogCommentIcon" /><a href='<%# Eval("AuthorUrl")%>' target="_blank" rel="nofollow"><%# " " + Eval("Author")%></a> <%# Eval("Date")%></div>
<div class="commentText">
<%# Eval("Content") %>
</div>
</div>
</ItemTemplate>
<EmptyDataTemplate>
</EmptyDataTemplate>
<LayoutTemplate>
<div id="itemPlaceholderContainer" runat="server">
<span id="itemPlaceholder" runat="server" />
</div>
</LayoutTemplate>
</asp:ListView>
</div>
</ItemTemplate>
<EmptyDataTemplate>
</EmptyDataTemplate>
<LayoutTemplate>
<div id="itemPlaceholderContainer" runat="server">
<span id="itemPlaceholder" runat="server" />
</div>
<div class="dataPagerWrap">
<asp:DataPager ID="ListViewpager" runat="server" PagedControlID="ListView1" PageSize="30" QueryStringField="page">
<Fields>
<asp:NextPreviousPagerField ShowFirstPageButton="True" ShowNextPageButton="False" ShowPreviousPageButton="False" FirstPageText="«" ButtonCssClass="dataPagerBackForward" />
<asp:NumericPagerField ButtonCount="8" CurrentPageLabelCssClass="dataPagerCurrent" NumericButtonCssClass="dataPager" PreviousPageText="..." NextPageText="..." NextPreviousButtonCssClass="dataPagerBackForward" />
<asp:NextPreviousPagerField ShowLastPageButton="True" ShowNextPageButton="False" ShowPreviousPageButton="False" LastPageText="»" ButtonCssClass="dataPagerBackForward" />
</Fields>
</asp:DataPager>
</div>
<div class="padding"></div>
</LayoutTemplate>
ALTER PROCEDURE [dbo].[sp_blog_GetComments]
(
@article int
)
AS
SET NOCOUNT ON;
SELECT
post_Comments.Author,
post_Comments.AuthorEmail,
post_Comments.AuthorUrl,
post_Comments.Content,
post_Comments.Date,
post_Comments.commentId
FROM post_Comments
INNER JOIN
posts
ON post_Comments.postId = posts.postId
WHERE(post_Comments.postId = @article)
AND (post_Comments.IsApproved = 1)
AND (post_Comments.ParentId IS NULL)
AND (posts.IsPublished = 1)
AND (posts.PublishOnDate <= GETDATE())
SELECT
Author,
AuthorEmail,
AuthorUrl,
Content,
Date,
ParentId
FROM post_Comments
WHERE (postId = @article)
AND (IsApproved = 1)
Хранимая процедура:
ALTER PROCEDURE [dbo].[Sp_blog_getcomments] (@article INT)
AS
SET nocount ON;
SELECT post_comments.author,
post_comments.authoremail,
post_comments.authorurl,
post_comments.content,
post_comments.date,
post_comments.commentid
FROM post_comments
INNER JOIN posts
ON post_comments.postid = posts.postid
WHERE ( post_comments.postid = @article )
AND ( post_comments.isapproved = 1 )
AND ( post_comments.parentid IS NULL )
AND ( posts.ispublished = 1 )
AND ( posts.publishondate <= Getdate() )
SELECT author,
authoremail,
authorurl,
content,
date,
parentid
FROM post_comments
WHERE ( postid = @article )
AND ( isapproved = 1 )
1 ответ
Один подход, который я помню где-то, заключался в том, чтобы вместо использования идентификатора комментария и идентификатора родителя комментарии имели идентификатор комментария и "ключ сортировки", который представлял собой объединение всех идентификаторов комментариев их предков.
Например, если на комментарий 1 было два ответа, комментарии 2 и 3, ключи сортировки были бы:
1 : 0001
2 : 0001.0002
3 : 0001.0003
Тогда, если кто-то ответил на комментарий 2, это было бы..
4 : 0001.0002.0004
Поэтому, если вы выберете все комментарии и отсортируете по этому ключу сортировки, они будут выпадать в правильном порядке.
Затем, чтобы сделать отступ, вы просто смотрите на длину ключа сортировки, чтобы увидеть, насколько глубокий уровень комментария, и сделаете отступ в соответствующем количестве.
Добавить комментарии легко: ключ сортировки нового комментария - это просто ключ сортировки родителя, в конце которого добавляется его собственный идентификатор.