做CMS最基本的一个功能就是做一个栏目导航,如果这个导航想做成动态的(即需要从数据库里提取数据)那么要如何实现呢?
简单的方法——DataTable
一个表两个字段,把数据提取出来,放在DataTable里面,然后在页面里做一个循环,OK了。是不是很简单呢?如果看了我的代码,估计会有很多人提出异议,呵呵。这里就是想和大家详细讨论一下。
由于每个页面都要用导航,而且都是一样的,所以我建立一个UserControl(用户控件)来做这个导航。首先在.ascx页面里定义一个protected的DataTable。然后在Page_Load里面填充这个DataTable。三行代码搞定。
【代码】
protected void Page_Load(object sender, EventArgs e)
{
DataAccessLibrary dal = DALFactory.CreateDAL();
dtChannel = dal.ExecuteFillDataTable("SELECT channelName, URL FROM CMS_Channel ORDER BY Sort ");
dal.Dispose();
}
再看页面部分。
{ %>
<td><a class="t1" href="<%=dr[1].ToString() %>"><%=dr[0].ToString() %></a></td>
<%} %>
遍历一遍就可以了。如果您不喜欢Table的话,那么换成DIV也行,对于遍历来说是没什么区别的。
好了,搞定。下面开始讨论您的疑问。
1、 在页面里出现了SQL语句,这个是不对的,即使是在.aspx.cs里面也是不行的。
2、 用DataTable是不好的,要用实体类。
3、 dr[1].ToString()。这种写法是不明确、不易读的,谁知道“1”代表什么意思?
我这里并不是为自己辩解,只是想说一下我的想法。说一下我的想法总是可以的吧?
1、 对于栏目这个特定的问题来说,表名和字段名都是比较稳定的,变动的可能性不大,即使变动了,这个SQL语句里面也只出现了两个字段名和一个表名,变化了,改就行了。由于用了UserControl,和栏目数据库相关的都放在这里,所以改一处就可以了。
2、 只有两个字段,就要定义一个实体类?我觉得有点浪费。也许您觉得DataTable性能不如实体类。这个我一直没做过测试,不知道他们到底差了多少。在数据量大和数据量少的时候,都差了多少。有空的话,我也想做一下这个测试。就栏目来说,我觉得专门定义一个实体类,实在是太浪费了。
3、 dr[1] 。这个是从效率和预防变更的角度来考虑的。这个比用字段名要快一些,而且字段名字变更了,这个也是不用改的。这里只有两个字段,虽然1、0不易读,但是数量少,也可以勉强接受了。
小结,这种写法的结构如下:
看着有点复杂,其实还是那几行代码。数据库就不用说了,ADO.net是系统提供的,不用我们操心,数据访问函数库是我自己写的,都封装好了,编译成DLL直接引用调用就可以了,剩下的就是页面了。就是那几行代码。
当然,您可以说我这是狡辩,也可以说我是老顽固,呵呵。不过请先别着急写回复,请先看完整了,在回复也不迟。对吧。
两层
上面的写法只是针对个别的情况,表名、字段名比较稳定,字段数量少,只有一个地方使用的情况。其他情况确实就不太适合了。那么要怎么改呢?我们试着往“三层”的方向修改一下。
我们建立一个项目,作为“业务逻辑层”。在建立一个.cs文件,里面定义一个类,在加一个函数,在这个函数内些三行代码,就是上面.ascx.cs里面的那三行。而.ascx.cs里面就可以改成调用这个类的方式了。
这样就可以了吗?也不对呀,业务逻辑层里面同样不可以写SQL语句的。还有,这个类是写成静态的,还是非静态的?如果还有其他的类似的需求,那么是写到一个.cs文件里面,还是写到多个.cs文件里面。就是说这个类独占一个.cs文件,还是和其他的类放在同一个.cs文件里面?疑惑呀,不知道到底怎么写了。
小结:加入了一个业务逻辑层,结构如下:
三层
业务逻辑里面不让写SQL,那么就在建立一个项目,作为数据层,在建立一个.cs文件,在定义一个类,在写一个函数,把上面那三行拿过来,原先的地方在改成调用这个函数。
这回可以了吧,数据层里面是可以写SQL语句的。也是三层了,三个项目了呀,一层一层往下调用。
但是回过头来看看,页面里调用一个类,得到了DataTable,这个是简洁了,但是业务逻辑层呢?一个类,一个函数,一行调用的代码,整个一个传声筒。数据层,虽然有三行代码,但是有效地就是那个SQL语句。如果数据库有变动,还是要修改,虽然不用满世界找SQL语句了,只在这个数据层里面找就可以,但是针对这个具体的问题,这么做有什么优势呢?
也许您会说,我这个根本就不是三层!不是说做了三个项目,把原来放在一起的代码分别放在了三个地方就是三层了。恩,我也觉得不是。三层怎么可能是这样?
但是真正的三层又是什么样子呢?真的很是不清楚。
这些是我的思考过程,拿出来和大家讨论一下,如果只有我一个人是这么写的,这么写代码的,那么我向大家道歉:多不住大家,占用了大家宝贵的时间,看这么无聊的贴子。
如果还有人也是有类似的想法,或者对三层很迷茫,那么请各位高手帮帮忙,针对这个具体的问题,讲一讲用三层要怎么写代码。哦,对了,我很穷,如果您要收费的话,那我还是迷茫吧。
小结:现在的结构。
实体
上面一直是用DataTable的,是不是要换成实体类呢?换成实体类就是三层了吗?就是面向对象了吗?同样,没那么简单吧。
实体类是做什么的呢?仅仅是传递数据的吗?太浪费了吧。
更换数据库
三层的一个目的是要应对数据库的变化,如果数据库变更了,那么只需要修改(或者是改一下标记)数据层就可以了,其他的地方不用改。
要应对各种数据库,就要定义一个接口,然后各个数据层实现不同数据库的访问方式。
那么针对这个具体的问题我们来看看,请教一下,这个SQL语句在哪种关系型数据库里不能运行,或者是得到的结果不一致呢?应该是没有吧。那么还有必要为这个功能而设计一个接口在分别实现吗?
有没有必要?什么情况下适合?要不要统一?
终于到了最后一个问题了。说了半天,我都是针对这一个具体的问题来说的,您会说这个具体的问题太简单了,根本用不着三层。但是那么复杂的就需要了。另外从整体的角度来说,一个项目、一个产品,甚至一个公司,都应该有一个统一的方式,不能一个页面一层,另一个页面三层,这样不就乱了吗?你让新人怎么看?这个确实是个问题,自己写倒是可以清楚,哪些地方是什么形式的,但是对于其他人来说就头晕了,到底是什么形式呀?
那么就要统一吗?即使对于个别情况,并不是适合的,但是也要配合大局、符合整体设计?一直都是以自己的方式来写项目,也不知道其他人是怎么做的。
解决方向只有一个吗?肯定不是的,还有其他很多解决方向。只是都是非主流而已。
还是不会写结尾,那么就以一个问题来结尾吧。
请问,针对这个具体的问题要如何解决?一层?三层?还是其他的什么方式?
也许是不能孤立的看问题,要从整体来看?从整体看才可以?