这次做图书馆维护系统,是用B-S开发,对于B-S开发来说,几乎是没有经验,仅仅是跟着牛腩的ASP.NET视频写过一些代码,再加上B-S开发与C-S开发有很大的不同,所以这次做图书馆维护系统遇到了很多问题,新旧问题都有,下面就把关键的问题记录下来,以便查阅。
1.数据库字段命名噩梦。
在写数据库字段的时候,突发奇想,尽可能的把字段名写的简单,比如:不管是小组名称还是成员名称都用name,这样看着挺简洁,感觉良好,可当我写存储过程连接查询的时候傻眼了,清一色的name,根本不知道是哪个表的name字段,幸好可以通过加别名来区分。因此,以后在给数据库字段命名时,尽可能的写清楚字段的含义,尽量的区分一下字段,否则会造成很大的不便,虽然可以通过别名来解决,但是会大大增加代码量和出错的概率。
2.组合查询不如不组合。
第一次接触组合查询是做机房收费系统,以后一直感觉组合查询很不错。但是经过这次项目实战,我发现组合查询并不是很合理。
首先,以前之所以组合查询比较方便,是因为以前数据库设计的不合理,冗余太多,比如用户类型直接就和用户基本信息放在一起,并没有把用户类型提取出来放在一张表中,这样用组合查询就非常省时省力。但是合理的数据库设计在用户基本信息中只包含一个类型id,没有办法直接查询,总不能让用户根据id查询吧?必须要转换一下,这一转换就显得非常啰嗦了。当然,可以事先定义好一个视图,但是我也不喜欢这样做,因为视图说白了就是一段T-SQL语句,每次调用视图这个T-SQL语句都要执行一次,而且还可能查询出大量不必要的信息,除非是超大型连接查询,否则没必要用视图。
其次,用组合查询盲目性很大。比如我们可以按照用户类型查询用户,如果用组合查询,用户用自己输入类型,一旦输入错误,就查不到记录,用户怎么可能把系统所有用户类型记得清清楚楚?如果有这么好的记忆力,还用电脑干什么?我们完全可以用一个DropDownList控件,事先读取出所有的用户类型进行绑定,然后让用户来选择类型,而不是输入类型,这点用组合查询很难办到。
综上所述,组合查询实际上是省了程序员的事,苦了用户,所以不建议使用。
3.事件无响应。
DropDownList控件是非常常用的一个控件,以前在C-S开发中也没遇到过什么问题,但是这次在B-S中,它的SelectedIndexChanged事件竟然不触发,无论怎么操作,这个事件都不响应。上网一查,发现这是个普遍问题,而且出现这种问题的原因很多,五花八门,于是我便尝试着解决,这一尝几乎把网上的方法都用遍了也没解决我这个问题。靠人不如靠自己,我索性把DropDownList所有的属性都看了一遍,然后发现网上的教程只说了加AllowPostBack="true"这个属性,并没有说加AutoPostBack="true",于是我抱着试一试的心理加上了AutoPostBack="true"这个属性,果然事件可以响应了!原来问题就是这么简单,如果读者也遇到此类问题,可以尝试用我这个最简单的办法解决:AutoPostBack="true" AllowPostBack="true"
4.正则表达式要千锤百炼才能写入程序。
正则表达式具体是啥我就不说了,做项目必不可少的东东,有了正则表达式,轻松拒绝非法数据。虽然好用,但是一定要谨慎,一定要先测试好,再写入程序。这次开发项目,好些正则表达式我也没好好测试,就匆匆写入了程序,结果后来测试的时候,数据都是非法的。比如软件下载地址验证正则表达式,我只想到了http开头,忘了还有ftp下载呢。。。甚至还有迅雷下载等等。建议使用正则表达式的时候,如果前人写的正则能满足,最好用前人写的公认的正则,不要自己胡乱创造,很容易出错。。。如果自己写,一定要在正则表达式测试工具中测试完整在用到程序中。
5.我保存的值去哪了?
对于B-S开发,我可以说是0经验。在写页面后台代码(aspx.cs)时,我像C-S开发一样,定义了自己熟悉的变量,保存了很多标记以及一些实体类。感觉一切良好,但测试的时候,出了很多莫名其妙的错误,于是本小菜便设下断点,发现这些变量竟然是空的!明明值已经取出来了,为啥变量空了?经过一番调查,原来是这样:
“web不向winframe应用程序,因为它是通过客户端和浏览器进行交互的,也就是无状态的
也就是每一次新的请求,服务器都会重新构建界面
所以全局变量会被初始化是肯定的,因为你点击button实际上是向服务器发送了一个请求
由于asp.net的回发机制,在asp.net接到请求后,会重新加载界面包含重新分配变量的值,重新构建控件对象
其中要控件的信息时根据你提交的表单数据在构建的,其中包括一些隐藏域信息,然后再把最新的信息发送到客户端,也就是说在html页面呈现给客户端之前,页面对象被销毁而且所有的客户端信息被丢弃。
所以在下一次请求的时候又要重新构建”
这段话说的很明白了,原来web程序是无状态的,试图用变量在后台保存数据是非常错误的想法。那么怎么来解决捏?废话不多说,直接看下表:
作用范围 |
页面范围 |
会话范围 |
系统范围 |
对象 |
ViewState |
Session,Cookie |
Application,Static |
从这张表可以明确的看出应该使用什么对象,相信大家能根据自己需求轻松的选出自己需要的对象,对于本小菜的图书馆维护系统,页面范围的viewstate对象刚好满足需求。至于每种对象具体怎么用,google一下可以轻易的搜到,在此就不赘述了,不怕不知道,就怕不知道。还有一些需要说明的,当时在解决这个问题的时候,还找到一些其他的方法,比如在界面上放一个隐藏的label控件用来存放数据等等,这些方法虽然可行,但是太过于业余,而且并不是最好的选择,上边这张表应该是非常理想的解决方案。
既然提到了viewstate对象,顺便提一下一个比较常见的问题:如何用viewstate对象保存对象?我们经常会用到一些实体类对象,而有时候我们会尝试去保存这个实体类对象,用viewstate对象保存非常简单,和保存普通类型的数据一样(viewstate[“xxx”]=xxx;),唯一的区别就是:假如你要保存A类的对象,那么必须在A类定义前加上[Serializable]来序列化(序列化意思就是允许以二进制的形式保存)这个类(在public class A{}这条语句前边加[Serializable]),viewstate对象更强大的地方在于它不仅仅可以保存对象,而且可以保存对象数组,异常强大哦!
顺便再提一下,尽量不要使用系统范围的对象,因为它们会一直跟随系统,直到程序重启(不是没有人访问网站了程序就关闭重启了,是要手动从服务器上重启的!)!会消耗大量资源!
好了,这次的总结就写到这了,希望自己以后能逐渐进步,也希望大家能更上一层楼!