对于数据库字段为空时,在 B/S 结构下的处理方式很多,而到了 dotNet 时代,就和原来有了本质的不同,根本就在于更强调服务器的自行处理。下面一步一步地从大家最熟悉的东西开始说。
首先用一个简单的 ASP+Access 留言本为例。数据库中对于每一个留言都有对应的一个回复,并且,只要回复了的留言将会用一个数据类型未 bit 的 messageStatus 字段来标记,回复了的用“ 1 ”来标记,否则用“ 0 ”(下面只给出关键部分代码,也就是判断 messageStatus 字段的值是真还是假):
1
2
3if messageRs("messageStatus")=False then
................ (此处省略了 html 代码)
1
2
3else
4
5set replyRs = Server.CreateObject("adodb.recordset")
6
7replySql = "select * from reply where messageId = " & messageRs("messageId")
8
9replyRs.Open replySql,conn
................ (此处省略了 html 代码)
1
2
3replyRs.Close
4
5set replyRs = nothing
6
7end if
而在 ASP.NET 中,由于程序代码已经完全可以和 html 代码分开,加上所提供的服务器端控件,使我们必须要找到一种适合于 ASP.NET 的方式。下面就直接进入我们的正题,和大家一起探讨在 ASP.NET 如何更好的实现。
下面列出笔者所知道的三种方法。下面还以留言板为例。
** 第一种—— **
可以这样解决,在 cs 页里写一函数,用于判断一个帖子是否有回复,如果有回复,则返回回复的内容,没有则返回“无回复”。然后把这个方法绑定到 DataGrid 或者 DataList ,或者 Reapter 空间的 itemtemplate 中的一个 Label 控件上。
下面是一个例子,用于显示某个图片,首先用 IsImageAvailable() 方法判断是否存在这幅图片,返回是一个布尔值,从而控制 img 控件和 Label 控件是否显示 . 如果有图片,则 img 控件显示,否则显示 Label 控件。
1<asp:templatecolumn headertext="Photo" runat="server">
2<itemtemplate>
3<img runat="server" src='```
4#"images\\\" + DataBinder.Eval(Container.DataItem, "lastname") + ".bmp"
5```' visible='```
6#IsImageAvailable(DataBinder.Eval(Container.DataItem, "lastname").ToString())
7```' width="50"/>
8<asp:label runat="server" text="<i><small> 没有图片可显示。 </small></i>" visible='```
9#IsImageAvailable(DataBinder.Eval(Container.DataItem, "lastname").ToString())
10```'></asp:label>
11</itemtemplate>
12</asp:templatecolumn>
** //IsImageAvailable() ** ** 函数 ** ** **
private bool IsImageAvailable(String strLastName)
{
String strImageFile = "images\" + strLastName + ".bmp";
return File.Exists(Server.MapPath(strImageFile));
}
解决思路大概就是这样,当没有图片时用 Label 控件显示 "No picture available" 。
** 第二种—— **
留言板的数据显示使用 DataGrid 控件,那么就容易了。使用 DataGrid 控件显示数据的时候,如果字段值为 NULL ,它会自动默认为空。所以我们可以把数据存为一个 DATASET, 然后再绑定到 DataGrid 上,使用 FOR 循环来判断,如果一个字段为空,如下赋值:
for (int i, i<ds.table[0].rows.count,i++)
{
if ds.table[0].row[i][" 字段名 "] = null
{
ds.table[0].row[i][" 字段名 "] = " 未回复 ";
}
}
** 第三种—— **
直接只用 SQL 语句。大家先来看看这样一个 SQL 语句:
select GuestName,GuestContact,GuestEmot,PostTitle,PostContent,PostTime,PostIP,case when(ReplyContent is null) then ' 未回复 ' else ReplyContent end as reply from GuestBook order by Id desc
这里出现了一个 case when() then … else …end as ,下面来看看它的具体用法。
** CASE **
计算条件列表并返回多个可能结果表达式之一。
** CASE ** ** 具有两种格式: **
1 、简单 CASE 函数将某个表达式与一组简单表达式进行比较以确定结果。
2 、 CASE 搜索函数计算一组布尔表达式以确定结果。
两种格式都支持可选的 ELSE 参数。
** 语法 **
简单 CASE 函数:
CASE input_expression
WHEN when_expression THEN result_expression
[ ...n ]
[
ELSE else_result_expression
END
CASE 搜索函数:
CASE
WHEN Boolean_expression THEN result_expression
[ ...n ]
[
ELSE else_result_expression
END
** 参数 **
input_expression
是使用简单 CASE 格式时所计算的表达式。 Input_expression 是任何有效的 Microsoft® SQL Server™ 表达式。
WHEN when_expression
使用简单 CASE 格式时 input_expression 所比较的简单表达式。 When_expression 是任意有效的 SQL Server 表达式。 Input_expression 和每个 when_expression 的数据类型必须相同,或者是隐性转换。
n
占位符,表明可以使用多个 WHEN when_expression THEN result_expression 子句或 WHEN Boolean_expression THEN result_expression 子句。
THEN result_expression
当 input_expression = when_expression 取值为 TRUE ,或者 Boolean_expression 取值为 TRUE 时返回的表达式。 result expression 是任意有效的 SQL Server 表达式。
ELSE else_result_expression
当比较运算取值不为 TRUE 时返回的表达式。如果省略此参数并且比较运算取值不为 TRUE , CASE 将返回 NULL 值。 Else_result_expression 是任意有效的 SQL Server 表达式。 Else_result_expression 和所有 result_expression 的数据类型必须相同,或者必须是隐性转换。
WHEN Boolean_expression
使用 CASE 搜索格式时所计算的布尔表达式。 Boolean_expression 是任意有效的布尔表达式。
** 结果类型 **
从 result_expressions 和可选 else_result_expression 的类型集合中返回最高的优先规则类型。
那么,总结一下上面说过的三种方法:
1、 第一种方法,需要额外写一个处理函数。增加了工作量;
2、 利用了 dotNet 中的 DataSet ,对于能熟练运用的朋友来说不成问题,但是对于初学者这个就有点困难了。而且也没有从减少代码量角度来考虑;
3、 充分利用了 SQL 语句,将空字段的处理完全交给服务器来完成,不需要额外写任何的代码。
其实,不管是做 B/S 结构的程序还是做 C/S 结构的,都离不开和数据库关联,那么一个好的 SQL 语句,将会带来极大的方便。 DotNet 时代的到来,将会进一步加快我们走向完整的三层体系结构,如上面说到的程序中直接利用 SQL 语句将是不规范的,以后的程序都将分为数据层、中间层、应用层,那么数据层的开发,其实还是直接、或者间接的和 SQL 语句关联,所以充分挖掘现有的 SQL 语句的功能将会非常有必要。