2

ASP.net 4.0 および sql server 2008 でブログの作成に取り組んでおり、スレッド化されたコメント システムの作成方法を学びたいと考えています。スレッド化とは、各コメントに返信リンクがあり、コメントが返信であるコメントの下にインデントされていることを意味します。そのため、記事自体に返信するか、コメントに返信することができます。

これはフォーラムやブログで非常に一般的ですが、これがどのように行われるかを説明し、コード例を示す記事を見つけることができません。

以下は私が作成したものですが、1 レベルの深さしか機能しません。再帰的にしたいので、深さのレベルに制限はありません:. これどうやってするの?アドバイスやコード サンプル付きの記事は素晴らしいものです。

コメント データベース テーブル

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>&nbsp;&nbsp;<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>&nbsp;&nbsp;<%# Eval("Date")%></div>
        <div class="commentText">
            <%# Eval("Content") %>
            <div><span class="btnCommentReply"><a href='<%# "article.aspx?article=" + Request.QueryString["article"] + "&amp;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>&nbsp;&nbsp;<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>&nbsp;&nbsp;<%# 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 ) 
4

1 に答える 1

10

どこかで見た覚えのあるアプローチの 1 つは、コメント ID と親 ID を使用するのではなく、コメントにはコメント ID と、その祖先のすべてのコメント ID を連結した「ソート キー」がありました。

たとえば、コメント 1 にコメント 2 と 3 の 2 つの返信がある場合、並べ替えキーは次のようになります。

1 : 0001
2 : 0001.0002
3 : 0001.0003

次に、誰かがコメント 2 に返信した場合、それは..

4 : 0001.0002.0004

したがって、すべてのコメントを選択してこの並べ替えキーで並べ替えると、正しい順序で並べ替えられます。

次に、インデントを行うには、並べ替えキーの長さを見て、コメントが何レベルの深さであるかを確認し、適切な量だけインデントします。

コメントの追加は簡単です。新しいコメントのソート キーは、単に親のソート キーであり、独自の ID が最後に追加されます。

于 2010-09-22T06:54:32.970 に答える