Portal Starter Kit 学习之-问题答复列表

2009012223521589.jpg

在Portal Starter Kit中,用嵌套DataList实现了如上图所示的问题及答复列表,感觉不错,一种实现思路。特将该实现思路摘取出来,当然其中也存在一些小问题,不过基本上还是不错的。

1.数据表的设计

在该实现中,只设计了一张表Portal_discussion。在一般的类似功能的实现中,一般是两种表:一个表存放的是顶层问题描述表,另一个存放的是问题的回复。但在Portal Starter中,只设计了Portal_discussion一个表,在该表中同时存放了问题以及问题的回复。表结构如下图所示。

2009012223495868.jpg

其中,ItemID为自增列;ModuleID为模块ID。其最重要应用的是字段DisplayOrder,我们可以发现

该字段是nvarchar(750),从字段的英文名字上,我们可以将其翻译为“显示顺序”。那么用该字段是怎么实现的显示顺序的呢?其实,在该字段中存放的是该问题上层问题的DisplayOrder值+本次发表问题的时间,所形成的新的字符串值(日期),如下图所示。

2009012223511631.jpg

2.DataList

该功能的实现主要利用了嵌套DataList来实现的。代码如下:

0 1 < asp:datalist id ="TopLevelList" runat ="server" DataKeyField ="Parent" ItemStyle-Cssclass ="Normal" width ="98%" >
0 2 < ItemTemplate >
0 3 < asp:ImageButton id ="btnSelect" ImageUrl='<%# NodeImage((int)DataBinder.Eval(Container.DataItem, "ChildCount")) % >' CommandName="select" runat="server" />
0 4 < asp:hyperlink Text='<%# DataBinder.Eval(Container.DataItem, "Title") % >' NavigateUrl=' < %# FormatUrl((int)DataBinder.Eval(Container.DataItem, "ItemID")) % >' Target="_new" runat="server" ID="Hyperlink1" />,
0 5 from
0 6 < %# DataBinder.Eval(Container.DataItem,"CreatedByUser") % >
0 7 , posted
0 8 < %# DataBinder.Eval(Container.DataItem,"CreatedDate", "{0:g}") % >
0 9 </ItemTemplate>
10 < SelectedItemTemplate >
11 < asp:ImageButton id ="btnCollapse" ImageUrl ="~/images/minus.gif" runat ="server" CommandName ="collapse" />
12 < asp:hyperlink Text='<%# DataBinder.Eval(Container.DataItem, "Title") % >' NavigateUrl=' < %# FormatUrl((int)DataBinder.Eval(Container.DataItem, "ItemID")) % >' Target="_new" runat="server" ID="Hyperlink2" />,
13 from
14 < %# DataBinder.Eval(Container.DataItem,"CreatedByUser") % >
15 , posted
16 < %# DataBinder.Eval(Container.DataItem,"CreatedDate", "{0:g}") % >
17 < asp:DataList id ="DetailList" ItemStyle-Cssclass ="Normal" datasource="<%# GetThreadMessages() % >" runat="server">
18 < ItemTemplate >
19 < %# DataBinder.Eval(Container.DataItem, "Indent") % >
20 < img src="<%=Global.GetApplicationPath(Request)% >/images/1x1.gif" height="15">
21 < asp:hyperlink Text='<%# DataBinder.Eval(Container.DataItem, "Title") % >' NavigateUrl=' < %# FormatUrl((int)DataBinder.Eval(Container.DataItem, "ItemID")) % >' Target="_new" runat="server" ID="Hyperlink3" />,
22 from
23 < %# DataBinder.Eval(Container.DataItem,"CreatedByUser") % >
24 , posted
25 < %# DataBinder.Eval(Container.DataItem,"CreatedDate", "{0:g}") % >
26 </ItemTemplate>
27 </asp:DataList>
28 </SelectedItemTemplate>
29 </asp:datalist>

3.三个重要的SQL存储过程

1.增加一个问题。不管增加的是顶层问题或是对某个问题的回复问题,都可以利用该存储过程。

0 1 CREATE PROCEDURE Portal_AddMessage
0 2 (
0 3 @ItemID int OUTPUT ,
0 4 @Title nvarchar (100 ) ,
0 5 @Body nvarchar (3000 ) ,
0 6 @ParentID int ,
0 7 @UserName nvarchar (100 ) ,
0 8 @ModuleID int
0 9 )
10
11 AS
12 / * Find DisplayOrder of parent item * /
13 DECLARE @ParentDisplayOrder as nvarchar (750 )
14 SET @ParentDisplayOrder = ""
15
16 SELECT
17 @ParentDisplayOrder = DisplayOrder
18 FROM Portal_Discussion
19 WHERE
20 ItemID = @ParentID
21
22 INSERT INTO Portal_Discussion
23 (
24 Title ,
25 Body ,
26 DisplayOrder ,
27 CreatedDate ,
28 CreatedByUser ,
29 ModuleID
30 )
31
32 VALUES
33 (
34 @Title ,
35 @Body ,
36 @ParentDisplayOrder + CONVERT ( nvarchar (24 ) , GetDate ( ) , 21 ) ,
37 GetDate ( ) ,
38 @UserName ,
39 @ModuleID
40 )
41
42 SELECT
43 @ItemID = @@Identity
44
45 GO

【说明】该存储过程中,对于参数@ParentID的值,如果是新增的问题,@ParentID=0;如果是回复某个问题的,那么@ParentID=那个问题的ItemID。该存储过程的实现思路是:

(1)声明一个@ParentDisplayOrder as nvarchar(750)

(2)根据@ParentID的值来,查找父问题的DisplayOrder字段的值,并存储到@ParentDisplayOrder变量中

(3)向表中插入数据。其中的关键是在DisplayOrder字段的赋值时,@ParentDisplayOrder + CONVERT( nvarchar(24), GetDate(), 21 )。其中CONVERT是用来将GetDate()获得日期做了格式化,会返回类似如下值:2009-01-22 23:16:09.807(长度为23,下面的获取顶层问题列表的存储过程会用到)。

(4)最后将新增加的问题的ItemID返回。

SELECT @ItemID = @@Identity

2.获取顶层问题列表;

0 1 CREATE PROCEDURE Portal_GetTopLevelMessages
0 2 (
0 3 @ModuleID int
0 4 )
0 5 AS
0 6
0 7 SELECT
0 8 ItemID ,
0 9 DisplayOrder ,
10 LEFT (DisplayOrder , 23 ) AS Parent ,
11 ( SELECT COUNT ( * ) -1 FROM Portal_Discussion Disc2 WHERE LEFT (Disc2 .DisplayOrder , LEN ( RTRIM (Disc .DisplayOrder ) ) ) = Disc .DisplayOrder ) AS ChildCount ,
12 Title ,
13 CreatedByUser ,
14 CreatedDate
15
16 FROM Portal_Discussion Disc
17
18 WHERE
19 ModuleID =@ModuleID
20 AND
21 ( LEN ( DisplayOrder ) / 23 ) = 1
22
23 ORDER BY
24 DisplayOrder
25
26 GO

由于在该系统中,顶层问题,以及对顶层问题的回复都在一个表里,而在显示的时候,我们需要只显示顶层的问题列表,所以,该存储过程的主要目的是获取顶层问题列表。该存储过程的返回值,包括了顶层问题的基本信息,同时还包含了一个新的字段ChildCount,返回的是每个顶层问题的回复数量。用于控制在DataList中,图标的显示。回复数量>0的显示一个+号图标,没有回复数量的显示点图标。主要的是看明白这句:

11 ( SELECT COUNT ( * ) -1 FROM Portal_Discussion Disc2 WHERE LEFT (Disc2 .DisplayOrder , LEN ( RTRIM (Disc .DisplayOrder ) ) ) = Disc .DisplayOrder ) AS ChildCount ,

3.获取某个指定问题。

该存储过程根据@ItemID参数,获取相应问题的信息。其中还包括了两个新字段信息。NextMessageID和PrevMessageID。

CREATE PROCEDURE Portal_GetSingleMessage
(
@ItemID int
)
AS

DECLARE @nextMessageID int
EXECUTE Portal_GetNextMessageID @ItemID , @nextMessageID OUTPUT
DECLARE @prevMessageID int
EXECUTE Portal_GetPrevMessageID @ItemID , @prevMessageID OUTPUT

SELECT
ItemID ,
ModuleID ,
Title ,
CreatedByUser ,
CreatedDate ,
Body ,
DisplayOrder ,
NextMessageID = @nextMessageID ,
PrevMessageID = @prevMessageID

FROM Portal_Discussion

WHERE
ItemID = @ItemID

其中获取NextMessageID(PreMessageID类似)的存储过程如下:

0 1
0 2 CREATE PROCEDURE Portal_GetNextMessageID
0 3 (
0 4 @ItemID int ,
0 5 @NextID int OUTPUT
0 6 )
0 7 AS
0 8
0 9 DECLARE @CurrentDisplayOrder as nvarchar (750 )
10 DECLARE @CurrentModule as int
11
12 / * Find DisplayOrder of current item * /
13 SELECT
14 @CurrentDisplayOrder = DisplayOrder ,
15 @CurrentModule = ModuleID
16 FROM Portal_Discussion
17 WHERE
18 ItemID = @ItemID
19
20 / * Get the next message in the same module * /
21 SELECT Top 1
22 @NextID = ItemID
23
24 FROM Portal_Discussion
25
26 WHERE
27 DisplayOrder > @CurrentDisplayOrder
28 AND
29 ModuleID = @CurrentModule
30
31 ORDER BY
32 DisplayOrder ASC
33
34 / * end of this thread? * /
35 IF @@Rowcount < 1
36 SET @NextID = null
37
38 GO

 

其他细节,请看源代码吧。困了,睡觉了。

 

 

 

 

 

转载于:https://www.cnblogs.com/lzm525/archive/2009/01/22/1380123.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值