不谋万世者,不足谋一时;不谋全局者,不足谋一域。君子敏于事而慎于言 新浪微薄:土司阿哈

Asp.Net 三层式Web应用程序开发 - Part.1

上一篇 / 下一篇  2008-12-20 14:04:28 / 个人分类:软件开发相关

1208328177
  • 自动化测试:
  • 测试文档:

 

引言

51Testing软件测试网 S0k)} \/|2B5P*_;v*C

本文是 “使用Asp.Net构建三层式Web 应用程序” 系列文章的第一部分。在这一系列文章中,我将系统的讲述如何使用 Asp.Net 设计、构建、实现三层式Web应用程序。本文的读者应该是有一定Asp.Net基础的开发者,同时要求对数据库、C#、Ajax、Web Service也有一定的了解。这系列文章使用我目前正在使用的一个“个人理财程序”作为范例讲解,这个程序非常小,只有三个表,但麻雀虽小五脏俱全,我主要想利用它为大家阐明一些概念,可能功能并不完备,但对于教程所讨论的主题没有影响,感兴趣的话可以自行扩展它。51Testing软件测试网$^+SrE`l8kI

51Testing软件测试网4A'}h3z pAPU

古人云:条条大道通罗马。所以,我这里讲述的,只是我个人的三层式Web应用程序实现,并不是说只有这一种实现方法,也不能说明这种实现方法是最好的。51Testing软件测试网S#~ ZtY|f'iq

  • 这系列文章计划分为五个部分,其中每个部分的内容如下:
  • Part 1. 讲解三层式Web应用程序的概念,数据访问层的实现方式,“个人理财程序”的程序介绍以及 需求分析。
  • Part 2. 讲解 系统的概要、详细设计,数据库的实现,业务层对象类的实现步骤和方法。
  • Part 3. 讲解 数据访问层 和 业务逻辑层 的代码实现。
  • Part 4. 讲解 用户界面层 的实现,以及如何使用 ObjectDataSource 调用业务逻辑层中的对象和方法。
  • Part 5. 讲解如何为 Part 4. 中实现的部分加上 Web Service 和 Asp.Net Ajax。

1PwJ,yJ%R0以下是几点说明:51Testing软件测试网iOj$u,F C/[Mss8\

  • 本文中,我有时候会说到“用户界面层”,有时候会说到“表现层”,这两个在本系列文章中是一回事。
  • 阅读本文前推荐阅读我的另一篇文章数据库对象命名参考
  • 本系列文章的 Source Code 和 T-SQL 脚本将会在所有Part全部发布后提供下载。
51Testing软件测试网v&W d3As'|*T'w'f5z

本系列文章使用的开发环境是 VS 2005 + SQL Server 2000,操作系统Windows Server 2003 Enterprise Edition。T-SQL 代码我只在 SQL Server 2000 下测试了,如果在 SQL Server 2005下不能通过,请反馈给我。

W| C]8y0

三层式开发介绍

iK K`w4{0RRf0分层式开发是一种开发模式,在这种模式中,用户界面层(用户所看到和与其交互的那部分)、业务逻辑层(业务规则(比如本例中每天的开销不能为负数)和业务对象)、以及数据访问层(对数据库进行查询和操作),从代码的角度来看,是分开的。

|T%i+Xg-e7l;R Yk0

'@Z {N&Rx.N ])fi0这种模式具有很多的优点:51Testing软件测试网sx%h{ A,d(w

  1. 你的代码非常的“干净”。可以试想一下,如果你把提交表单的ADO.NET数据库操作全都写到页面的 CodeBehind文件中,会是多么的凌乱?
  2. 更好的可维护性,程序员之间的分工明确,各层之间只需要知道调用接口就可以了,而不需要知道是如何实现的。
  3. 更好的可移植性,可以联想一下 微软的数据访问技术 从 ODBC 到 OLEDB 到 ADO再到 ADO.Net 1.1 一直到如今的 ADO.NET 2.0,几乎每三年就会有一次变革,采用分层式开发,可以在系统升级的时候更少的受到影响。
  4. 更好的对分布式应用程序的支持。

NOTE:提到分布式应用程序时常会遇到两个英文单词: Tier 和 Layer ,这两个单词的意思翻译过来都是 “层”,但是有什么区别呢?老外通常提到Tier 的时候,指的是物理上分层;提到 Layer 的时候,常指的是逻辑上分层。物理上分层说的简单点,就是用户界面层在一台服务器,业务逻辑层在一台服务器,数据访问层又在另一台服务器(也可以表现层和业务层在同一台服务器,数据访问层在一台服务器,总之三个层不在一台服务器)。而逻辑上分层我现在正在讲述,很容易就想得通:如果物理上分层了,逻辑上也一定分层了;但如果逻辑上分层了,物理上不一定是分层的,可以部署在同一台服务器上,比如我的这个“个人理财程序”。51Testing软件测试网F`+E!]NJm

51Testing软件测试网:C+R5b U&kJ^

为了给大家一个更生动的认识,我用 Visio画了个图给大家看看:

!_2X;m Q p F @0

:l6l}_n`{051Testing软件测试网x\o5}6U

51Testing软件测试网C"Bh `'cf%E

图1. 三层式程序结构图51Testing软件测试网[ h}R~ L

;Z A J}i `0这张图描述了这个应用程序中数据流动的大致方向。

LJ_Cu051Testing软件测试网3?*n)_,xS$P0d

请大家从用户和左边的箭头看起:

H,B#^*{?c0
  1. 用户浏览网页时,首先面对的是用户界面层或者说表现层,如果用户进行一个对数据库查询的操作,请求首先会发送到业务逻辑层。
  2. 业务逻辑层对用户提交的数据进行校验,如果有问题,将拒绝用户请求并给出错误提示;如果没有问题,业务逻辑层将用户请求递交给数据访问层。
  3. +数据访问层充当业务逻辑层与数据库之间的一个桥梁,把请求递交给数据库,不应该在这一层再去做一些数据校验的工作,来自业务逻辑层的数据应该被认为是无误的,这层的代码相对于业务逻辑层来说是很清爽的。
  4. 数据库进行查询后将结果集返回给数据访问层,接着再返回给业务逻辑层,最后呈现给用户。这是一个典型的冒泡过程。在这个过程中,任何没有Catch的异常都会抛出,冒泡到用户界面层,这也就是为什么你访问aspx的页面,看到的却是来自数据库的“Can’t connect to database”的原因。

个人理财Web程序介绍

O Iy!?!m6r\3bL#~0我是一个不会理财的人,在过去两年零一个月的时间,一毛钱都没有攒下,一个人的时候,我时常思索为什么我的钱总是来也匆匆去也匆匆,在现在老婆房子女朋友都没有的三无情况下,这样继续下去将会给我的人生带来深远的影响。51Testing软件测试网;HS3Y?h7Mn/[KL

51Testing软件测试网L$@i{9l7fY

沉默了许久之后,我终于觉悟了... ..我想做的第一件事,就是解决长期困扰我的头号问题 -– 我的钱都跑哪儿去了?于是,这个个人理财程序便应运而生了。51Testing软件测试网&{?cH`:kU7m1~4l'A

51Testing软件测试网 XV @c|Lob7pg

其实如果只是我一个人使用的话,只需要一个表,就足以构建这个应用程序了。我给这个表起名叫:DailyCost,用来记录每天的开销/收入项目,表的字段分别是:51Testing软件测试网sFh*p9CMv9LO

CostId:自动编号,主键。51Testing软件测试网:k.l BdR
Type:0,表示开销;1,表示收入51Testing软件测试网ER4OE;XW;` Cw
Purpost:开销用途/收入来源51Testing软件测试网0[#\*`;vk$@,j:M
Amount:数额
6VJ;{:P7P0CostDate:开销日期51Testing软件测试网cM.TM9O5oO-a N-W

x&~$u'WY/?B U] G0但是,这么好的程序(NOTE:和我一样不会理财的人应该也不少吧?),只有我一个人用简直太浪费了,让我们来对它进行了一下扩展,让更多的人可以使用吧。这样,就很有必要再加一个 User 表,记录使用此系统的用户,这个表应该包含如下字段:51Testing软件测试网4r7WW|4T#q E ]8X

UserId:自动编号,主键。
uk[1w,g#N3ny0Name:用户的名字
g-Fcq(U(e(H0BirthDay:生日51Testing软件测试网Bw.EQ#Vq$B9T4T
Phone:用户的电话

9iL,q} K \!E:p3A0

!Xa o0`6\#U F0此时,应该修改DailyCost表,以实现参照完整性(NOTE:也叫外键约束)。给DailyCost表再加一个字段:FKUserId,此条消费记录是属于哪位用户的。

9J?;HB0@0Os0

-c\oL!dg-Fg9]0在现在这个苦力都拿手机的时代,人们的Phone是会有很多的,比如手机一个,办公室一个,家里一个。所以,我们应该把Phone字段抽象出来,形成与User表的一对多关系。

"B:vo Jf5g YW | IVw0

建立 Phone 表,字段如下:51Testing软件测试网-c(pY1oD yBF u
PhoneId:自动编号,主键。51Testing软件测试网 b\_ v"BW5Y K
Number:号码
/s.c/w.h"_ rF5l0Type:0,手机;1,家里;2,公司;3,其他51Testing软件测试网nZ-kg7XMR3Ot0{
FKUserId:外键,此Phone是哪位用户的51Testing软件测试网*c{%|7k b9`kL$W

5wK,yuTH(suqV1n@_0OK,这部分就先介绍到这里,在后面的 概要/详细设计中会再次讲解。

AF5mH3v ~0

NOTE:概要设计和详细设计我合并了,因为这个应用程序比较小,合并到一起我想大家已经可以看明白,分开讲解可能会显得文章过于繁琐。51Testing软件测试网pzRl {%j4b

实现数据访问层的不同方式

与用户界面揉在一起的数据访问层

-cY.f,`!K"Q;V]"~!}N0这就是上面提到过的“初学者访问层”,将ADO.NET 代码揉到CodeBehind的事件处理中去,这种方法几乎没有可维护性,对数据库的任何改动,比如增减一个字段,或者给某个存储过程重新命名,都要导致修改大量的相关文件。另外,这种方法还有一个致命的缺点:无法实现代码重用。其实这种方法不应该称作“层”,但是为了文章的完备性,我还是在这里把它提出来。

`&@.^FL4c'gN2g`+`W0

j!S t s'dqv0用这种方式写的代码通常都是这样的:

v5N taB w0qH)N0

protectedvoidPage_Load(objectsender, EventArgs e)51Testing软件测试网/Mo"hCn*D$u:DRqp1F
{  51Testing软件测试网h+a P nxv([ s
 if(!Page.IsPostBack)51Testing软件测试网%F w7n}k
  {51Testing软件测试网6g*|]"M WZ
   stringsqlText = @"SELECT Purpose, Amount,
2q$Il5sr0        Type FROM DailyCostWHERECostId = 1";51Testing软件测试网 L;n;oGnB|b

2l!~[G&f0   using(SqlConnectionconn =
-X4p$Tj l+t0FJ0       newSqlConnection(ConfigurationManager.ConnectionStrings["JimmyCost"]
#s UtA~%O/X0j&]0        .ConnectionString))
j7[ \~V*}'? Cw0    {
!pw0W)?4p+e3u#}-F0     using(SqlCommandmyCommand =newSqlCommand(sqlText, conn))
v]1CPI}0      {51Testing软件测试网 [+f!q1}ZNW
        conn.Open();
5Mp+n)D$VJ {OU0       using(SqlDataReadermyReader = myCommand.ExecuteReader())
9a @dm;@p0        {51Testing软件测试网:J%| ZPpe
         if(myReader.Read())
8C5n-`:L(`0          {51Testing软件测试网2{}H U${ l
            txtPurpose.Text = myReader.GetString(0);51Testing软件测试网K1N0O;d+N0ip!C
            txtAmount.Text = myReader.GetString(1);51Testing软件测试网 [3`5br oMR
         txtType.Text = myReader.GetString(2);51Testing软件测试网,nXDAJ-t
         }
+O ?2rH,yvj0          myReader.Close();51Testing软件测试网a i_L"i*}$}$`S
        }
8`N9hig:b}"z"HEi0        conn.Close();
e \ L4E*p(H!r7|+B}J*Y0      }
fJ;r`4aoR|}y0    }51Testing软件测试网X8m|3W/B
  }
,q6@8Cux'G$y0}
Q:k-_.c\vY9a7nB(T0
3Ps |(w`)QW#t9Y0protectedvoidbtnSave_Click(objectsender, EventArgs e)
`&]C }B0{51Testing软件测试网;q:[-f}i ]f;~7u;cU
 stringsqlText = @"UPDATE DailyCost SET Purpose='{0}',
5@L_(U'?}1I0_0  Amount='{1}', Type ='{2}'WHEREId = 1";51Testing软件测试网:B?Y9H,q
 using(SqlConnectionconn =51Testing软件测试网#@8L,[|Pa*K(f
       newSqlConnection(ConfigurationManager.ConnectionStrings["JimmyCost"]
i^'Mg1K)GjhB5y7`0            .ConnectionString))
z#@%^M3e#rP0  {51Testing软件测试网M4jB+D{ q B-K8I
   stringsql =String.Format(sqlText,51Testing软件测试网&R*C?r"_d:R oh(M
           txtPurpose.Text, txtAmount.Text, txtType.Text);
0C*i1K,e?0   SqlCommandcmd =newSqlCommand(sql, conn);51Testing软件测试网*BB"n!o$e oE{aJb
    conn.Open();
5qlx-S\ V(T0    cmd.ExecuteNonQuery();51Testing软件测试网gd[2L l)DWh
    conn.Close();
$}2U!{,Lm*F-_$xsw0  }
.J(J]muR;hx#{0}51Testing软件测试网z]o.Y]:z"\[2i

使用SqlDataSource 作为数据访问层

JM,v%Y0Sh;`0]g0在这里我推荐给大家一本好书,由电子工业出版社出版的,奚江华写作的《圣殿祭祀的ASP.NET 2.0开发详解》。在这本书中,作者在第11章 — “新一代数据访问方式DataSource控件”中详细讨论了 SqlDataSource 的种种特性,其中,比较重要的就是使用代码后置的方法动态的创建和配置 SqlDataSource 控件,并提供对页面数据控件的绑定。这就提供了一种新的实现数据访问层的思路 – 使用SqlDataSource 作为数据访问层。

4U#PW)QU%i#R${L)\j0

KEC]R2t0在这里不得不说明一点,ObjectDataSource 其实就是完全自定义的 SqlDataSource 控件,想想看你是如何使用 SqlDataSource 的?我想你一定在前端页面通过拖拽控件的方式使用过SqlDataSource ,也一定注意到 SqlDataSource 的几个重要属性,SelectCommand、UpdateCommand 等,在使用 SqlDataSource 时,向导自动为你生成 Sql 语句(也可以自己写),然后显示在.aspx文件中,如果你实现了 UpdateCommand、InsertCommand (SelectCommand是必须要实现的),SqlDataSource 也就具有了相应的功能。而 ObjectDataSource 是如何运作的呢?它要求你自己写全部的Code以实现 Command,区别就是,你可以把这些Command全部封装到类或者说业务逻辑层中去。51Testing软件测试网'SuiGRw&n

51Testing软件测试网(A"Cj],P }f

好了,说了这么多,让我们看看使用SqlDataSource作为数据访问层的典型页面吧。

LT6Y[&}'U*~0

<asp:SqlDataSource  
%i[W$vxd_)Pa0ID="SqlDataSource1" runat="server"  
"Q-X3t EbOJ9e.B0ConnectionString="<%$ ConnectionStrings:JimmyConn %>"  51Testing软件测试网G(}\/i6h3W
DeleteCommand="DELETE FROM [DailyCost] WHERE [CostId] = @original_Id"
)slg[m:l wOw@/R0InsertCommand="INSERT INTO [DailyCost] ([Purpose], [Type],51Testing软件测试网H~(m2n g I bD9f^N
    [Amount], [CostDate]) VALUES (@Purpose,
y2O&R4N w8l"h:f2X0    @Type, @Amount, @CostDate)"
b1qy[2hK0SelectCommand="SELECT * FROM [DailyCost]"
u9R'n}2K(M0UpdateCommand="UPDATE [DailyCost] SET [Purpose] = @Purpose,
5_gv|$ZX0    [Type] = @Type, [Amount] = @Amount,51Testing软件测试网B]xW Yi
    [CostDate] = @CostDate WHERE [CostId] = @original_Id"  ōldValuesParameterFormatString="original_{0}"51Testing软件测试网/D%_gTo`
>
$U!ZtT8DN7|0<DeleteParameters>51Testing软件测试网)N/K/sI} c-[m9e]
    <asp:Parameter Name="original_Id" Type="Int32" />
9[,g*_V$}a-e0</DeleteParameters>
2f"s^2ZM8Q3l$oc0<UpdateParameters>
w)[]6b'n|@8i^0    <asp:Parameter Name="Purpose" Type="String" />
O T2H!i)_S1A3W0    <asp:Parameter Name="Type" Type="Bool" />51Testing软件测试网o_Kur*{
    <asp:Parameter Name="Amount" Type="Decimal" />
Ng5Gp2nb^.qBi U0    <asp:Parameter Name="CostDate" Type="DateTime" />51Testing软件测试网T8aq(PdMb8L.D _
    <asp:Parameter Name="original_Id" Type="Int32" />51Testing软件测试网.pe7k.aq9i?Ky
</UpdateParameters>51Testing软件测试网Pxw9R6m0wXV s
<InsertParameters>51Testing软件测试网'{4Y |cD4m
    <asp:Parameter Name="Purpose" Type="String" />
A4q#p3q S)_1@)A0    <asp:Parameter Name="Type" Type=" Bool " />
%`f5z BeVH0    <asp:Parameter Name="Amount" Type="Decimal" />51Testing软件测试网eqihq
    <asp:Parameter Name="CostDate" Type="DateTime" />51Testing软件测试网5P\"G/V6Bv$W
</InsertParameters></asp:SqlDataSource>51Testing软件测试网xi.YB o"~'G.}L

8B JZYW z6or` E~0很明显就可以看到,不仅关于数据访问的Sql 语句直接写到了 .aspx页面中,而且代码臃肿不堪。尽管你可以使用代码后置的方式去实现这些,但代价就是降低了开发效率,因为手写比你拖动控件、使用向导要慢得太多。

Zu0x4a/Dlh0

使用TableAdapter和 强类型的DataSet

*PDl6l3@$?0VS 2005 提供强类型的 DataSet ,可以通过 VS2005向导 来创建,熟练的话,是创建数据访问层最快的一种方式,微软官方站点www.asp.net,有一个关于数据访问的系列教程,目前出到快 70 章了(NOTE:我大概算了一下,可以出本900页的书了),仍在不断更新中,这个教程使用的就是这种模型。51Testing软件测试网(FMD@sH~AH'a-bS

4@%D2L}8N$Z(E3U5E)d @0这里我仅简要说明一下什么是强类型的DataSet,和普通的DataSet有什么区别,至于如何创建强类型的DataSet,需要一个独立的章节来介绍,我以后再发文章补上。51Testing软件测试网6t/o6j2} t6E@A

@)[9Z\xM0强类型DataSet(Typed DataSet)并不是 .NET 框架直接提供的一系列类,而是从DataSet类继承而来的,下图先给大家演示了传统的DataSet和它包含的各个元素之间的关系。

hu%dQ8pC QA051Testing软件测试网'\y `#x%Rh3U ^

51Testing软件测试网G?7\:M m z

8G5m*YoR1uA(y*o!B0这里黑色的菱形箭头表示的是合成的方向,下面这幅图中,空心的三角,表示的是泛化的方向。合成,说通俗一点,或者用数据库的术语来说(NOTE: 用在这里并不恰当,纯粹为了解说方便),就是多对一关系,拿这幅图来说,就是好多个 DataRow 合成了DataTable,同时DataTable 还可以有DataColumn,Constraint和DataRelation;同时,很多个DataColumn又合成了Constraint和DataRelation。最后,好多个DataTable和 DataRelation合成了DataSet。51Testing软件测试网7ox-@ T Xk/P

51Testing软件测试网T)sVSs+{1z'n-c

相比之下,强类型DataSet是从这些类派生出来的。51Testing软件测试网1~4L.cT~S?a*`CX

51Testing软件测试网-X,S Eed#J

51Testing软件测试网3p0K,~N2YS6w9AL4d&h

1Fy^3owp#tt e3ZsX0这幅图该如何解读我就不详细解释了,留给大家一点思考的空间。51Testing软件测试网EiZd'YGc,Z

.m9w v#o1aO[0那又为什么称它们为“强类型”DataSet呢?因为在强类型DataSet中,是使用一种类型安全的方式来使用其中的每一个对象,光是说术语很难懂什么叫类型安全的方式,让我们看下面的代码范例吧。51Testing软件测试网$A+k6I4E mV

X9R#LW yb2b0我们先看一段使用传统DataSet的代码。

.q%U$[7S\m0T;[f9],Ak0

// 前面省略部分代码
%b._?I%@m,LA&dt0
SqlDataAdapterdaDailyCost =newSqlDataAdapter(“Select * From DailyCost”, conn);
6Y v!M;u#x,G[;w0
c!z3} mUw M@0DataSetdataSet =newdataSet;51Testing软件测试网y|NoAjf!m

}0|;U&N'o~YG%l0daDailyCost.Fill(dataSet, “ShowCost”);51Testing软件测试网+tHG-F.P h)S

~t7md W0s{0Console.WriteLine(dataSet.Tables[“ShowCost”].Rows[0][“CostId”].ToString());51Testing软件测试网4w6UC)B](d

51Testing软件测试网2U&icGgl/_s

可以发现,我们在获取一个字段的值时,需要使用DataSet的索引器,逐步获得DataSet层次结构的每一个片段,直到最后抵达行级,在这个过程中,任何的拼写错误都会导致抛出异常。

-Zu.H'K_:{051Testing软件测试网$D7JQz:iY

现在再看看 强类型DataSet是如何运作的。

d&IXHp5NQ4`U0

//前面省略部分代码
;OB1DC~0
SqlDataAdapterdaDailyCost =newSqlDataAdapter(“Select * From DailyCost”,conn);51Testing软件测试网r4M\:B~2pB0E$Rc

@2@6B8\*{0//DailyCostTD 是实现了的强类型dataSet,至于如何实现,我以后会另写文章51Testing软件测试网)I2\COeE"XG5v*i
DailyCostTD dataSet =newDailyCostTD();
]qw+i7@E/v/}+Z051Testing软件测试网AEK$VI j7[F9O
daDailyCost.Fill(dataSet,”ShowCost”);
p)oF]p0
;@\&cd6| R0Console.WriteLine(dataSet.Customer[0].Purpose);

O_ g9akB0

O~'O:qg ^0在这里,大家似乎觉得这两个没太大区别,无非就是在 Console.WriteLine的时候少打几个字而已,其实不然,在你用强类型DataSet的时候,VS2005会提供智能提示(NOTE:就是打个i,int就显示出来了,你只要拍下空格就好了),这样,就大大降低了编写时发生手误的机会。

k'J%~wGb]051Testing软件测试网Z1mCm.h&xO(x

既然强类型DataSet这么好用,为什么不干脆使用它作为数据访问层呢?前面我也提到过,使用类型化DataSet是创建数据访问层最快的方式,你只需要建立一个.xsd数据集文件,然后拖拽控件,再使用向导设置一下基本就可以Run了。但是,代价就是几乎没有扩展性,因为代码都是自动生成的,你很难去修改它(NOTE:其实还是有办法可以改的,你可以通过写部分类的方式去扩展它),另外,重用性也比较差。

pc/Ip\,}/N^0

使用封装的ADO.NET数据访问层类

a!N_ N/B:@)\^0与“初学者访问层”相同的地方是:这种方式也是采用的全手写 ADO.NET 代码来实现的;不同的是,将所有对于数据库的操作封装到了一个类中,这个类是高度整合的,你甚至可以不加改动将它用在其它的项目中。51Testing软件测试网&Oy{-k:mKBw

51Testing软件测试网,|M~5H$H_Z'V-Z

我能想到这种方式,当然很多人也能想到,所以,网上的开源站点及一些个人站点已经提供了这个封装好的类的下载,其中大多是静态类,因为类作者水平高低不均,所以类的质量也是良莠不齐。另外,几乎所有这个类都约定俗成般起了同一个名字,叫做 -- SqlHelper 。

Y7iu _7n@A051Testing软件测试网6m@0^^%Y@.C

这里有一个比较不错的老外写的SqlHelper类,感兴趣的可以参考一下。51Testing软件测试网B+b+g+Zw `uz+Q*B!H

使用新一代的 LINQ

6T pv4Yq*Q2rq,FM0还有一种方式就是使用LINQ,很多人可能还是第一次听说这个名词,那么我就稍微的介绍一下:

.ar#Jgd#]:h)J%u z051Testing软件测试网Q;S,u,w)KbK

简单来说,Linq 就是帮助编译器理解和实现内存中保存的对象集合的一组特性。这样说可能比较绕口,Linq中有一个组件,称做Linq To Sql,它提供了一个在运行时将关系数据库数据处理成对象的底层机制,并且还不丧失关系数据库的查询功能。它通过将面向语的查询翻译成数据库可执行的查询语句,再将语句提交给数据库,然后把数据库返回的结果集映射成开发者定义的对象来完成。51Testing软件测试网Yy;q @)d

51Testing软件测试网(G^ zF%u7g0HRs

上面的说法如果没有实际动手体会一下,或者看一些范例,相信不是太好理解。在我的个人博客jimmyzhang.cnblogs.com上已经陆续发布了来自微软开发团队的ScottGu的“Linq To Sql介绍”系列文章,有兴趣的朋友可以去看一看。51Testing软件测试网!D;OcI H"^L['G

[4k!}'z(X#MIM.[0Ee0? a0不使用Linq的主要原因是它现在还处于Beta版本,正式发布时可能还会有改进。另外,目前的主机大多都只支持到.Net Framework 2.0,所以使用LINQ尚为时过早。51Testing软件测试网A%?-O`-x

使用自定义的业务逻辑层对象

CmSm$oJxN5N"|0终于,我们的主角登场了。很多情况下,业务对象只是一个由其他对象继承的简单的类,也可以实现一些接口让它变得更好用一些。在我们的这个系统中,Phone对象像下面这样:51Testing软件测试网6E|Y#y*H-q

publicclassPhone
/Q(q5E\?0{
s a _g6B!TCs m0   privateintphoneid = -1;
N%K6X ZsGJ0   privatestringnumber;
1g8gp|#h-s'`~0   privatePhoneTypetype;        // PhoneType是一个枚举51Testing软件测试网Nt.p?xJw {X
51Testing软件测试网E m]Y Q V y:r
   publicstringNumber{
G4i"g.j#f8f a0       get{returnnumber;}
+\ N8l'E:l0       set{number = value;}
4n(r$_N1eE5P-G_&~0    }51Testing软件测试网wuz Z b A
}    //以下代码省略

q|%I6YV9M'\051Testing软件测试网9Jem D:I:n,S@

在实践中,通常业务对象只包含数据,而关于对象操作的方法则封装到业务逻辑中去。

rIQJ}Gi,WR0

(asZ4mN6Z0好了,数据访问层的实现方法至此告一段落,下面让我们开始进行需求分析 吧。51Testing软件测试网9os$@U+FJ d7hN2t

需求分析

51Testing软件测试网.r.vR.eb.\

做任何开发之前,需求分析都是很重要的步骤,如果需求都没有搞好,就等于没有回答用户需要什么解决方案的问题,如果在需求分析不明确的情况下冒然进行开发,结果往往是苦战两个月,做出来的产品却不是用户想要的。另外,需求分析并不是一次成型的,在这个阶段,由于还没有深入到概要设计或者详细设计中去,对系统的理解可能并不完整,所以会时常回过头来修订需求分析。

.sVFQz051Testing软件测试网oLG:`*h

由于这个“个人理财程序”的用户和开发人员都是我自己,所以需求分析可以认为只是打打字而已。51Testing软件测试网 X3L#p%] z:M~v8i4Br?

G[0ot q0在这个Web应用程序中,我们要实现的功能主要有这些:

s N3J| FbBH0
  1. 要求可以添加、编辑、删除用户
  2. 要求可以添加、编辑、删除用户电话
  3. 要求可以添加、编辑、删除每日的开销项目
  4. 要求可以删除 某日、某月 的全部开销
  5. 要求可以查看某天、某月、某年的花费报表
  6. 要求可以统计每天、每月、每年各开销了多少钱
  7. 要求可以统计历史花钱最高的日期和开销/收益的数额
  8. 要求可以统计历史花钱最低的日期和开销/收益的数额
  9. 要求可以统计自系统运行以来总共开销了多少钱
  10. 要求可以统计自系统运行以来总共收益了多少钱
  11. 要求可以查看某个用户所有的联系方式

总结

51Testing软件测试网4PqI$T6c+w

本文是使用 Asp.Net构建三层 Web应用程序的第一部分。51Testing软件测试网)B+B&E/cs6D@

51Testing软件测试网F[RuXd7|d,P

我们首先了解了什么是三层式开发模式,接着提出了一个很现实的需要解决的问题,并对这个问题做了一些简单的分析。

~`9\ He051Testing软件测试网/L*F"Q Tn4Y3w2g

然后,我们花了很大的篇幅,讲解实现数据访问层的各种方式,并简要介绍了我们即将采用的方法。

1KU1y@u"a P051Testing软件测试网q2l S"^G O

最后,我们对这个“个人理财程序”做了一下简单需求分析。51Testing软件测试网4@-eOm1e L.]u

jixM1o^6Q0希望这篇文章能给你带来帮助。

W3L{7x#H1gWjc%s0

TAG: 软件开发相关

 

评分:0

我来说两句

Open Toolbar