原文:Duwamish7未来之路-数据交换(原创)
接着掉掉的文章继续说:
多层架构关键问题何在?-数据交换
其实这个问题很普遍,就是层与层之间通讯采用何种语言(不会是简体中文吧?)。以前在Com+的时候我常用数组(很笨吧?),数组的确够效率和易用。但是最大的问题是,数组的结构太单一,不能用来反应比较复杂的逻辑关系。这时候XML出现了,他的诞生给我们解决了以上的结构问题。但是XML还是不太够用或者说好用,于是微软给了我们DateSet,那种类似Recordset的感觉又回来了。
Recordset --小河
DateSet -- 大海
Duwamish 7巧妙采用dateset做为各层之间交换数据的方法,简化了许多以前必须的步骤,如装填数组或者生成XML流什么的。
Duwamish作为Vs.NET自带的例子,一定代表着MS想向开发人员传递的思想和开发技巧,记得以前学习PB时没有查看PB的例子程序,等走过很多弯路再看到PB的例程时发现,原来好的冥思苦想的方法、技巧,就在自已机器上安静的躺着呢!
一直想较仔细一点的学习研究一下Duwamish,但总是没有机会,现在系统上线,总算轻松一点而有点时间来和她来个亲密接触了:)
Duwamish解决方案总共有6个项目,结构上分为5层:业务外观层(BusinessFacade)、业务规则层(BusinessRules)、业务实体层(Common)、数据访问层(DataAccess)、业务展示层(Web).另外一项目为SystemFrameWork,顾名思意,主要是用来进行整个系统构架的一些配置、跟踪、日志等.
Common项目
1.让我们来看一看Duwamish7的数据结构,图1
2.对数据库中Book,Category,Customer,Order四个最主要的对象进行了业务实体封装,四个类均继承自DataSet,但类加入两个属性: [System.ComponentModel.DesignerCategory("Code")]、[SerializableAttribute],前一个属性的意思是指定当前类设计器属于某一类别。后一个属性标记当前类为可序列化类,使之可远程调用。
类中对数据库中表和表中字段进行了映射,部份类中还定义了相关的错误信息如
public const String EMAIL_FIELD_NOT_UNIQUE = "Email Not Unique";
3.在默认的构造函数中调用BuildDataTables()方法创建表结构并添加到DataSet中。BookData、CategoryData、CustomerData类中均只保存一个表,而OrderData类中保存有与订单相关的6个表信息。
DataSet中的表与数据库中物理表有的是一一对映,有的是一个物理表对应DataSet中多个表,而有的多个物理表对应Dataset中一个表.
4.Common项目中还有一个DuwamishConfiguration类,用来获取Web.Config文件中对Duwamish配置项,继承自IConfigurationSectionHandler接口。该接口定义如下协定:所有配置节处理程序必须在实现后才能参与配置设置的解析。该接口只有一个Create()方法,DuwamishConfiguration类中实现Create()方法,通过NameValueSessionHander实例baseHandler.Create()方法填充NameValueCollection setting,再调用
ApplicationConfiguration.ReadSetting()方法返回指定的某个配置信息。
疑问:
1.4个业务实体类均有一个支持序列化的构造函数如BookData类的
private BookData(SerializationInfo info, StreamingContext context) : base(info, context) {}
不是很明白,此4个类序列化没有特别的的引用对象,应该只要进行“基本序列化”即简单的在类前加Serializable 属性对它进行标记即可,为什么还要定义一个支持序列化的构造函数呢?是不是因为继承DataSet的原因??
2.系统什么时候,怎么样调用DuwamishConfiguration类的Create()方法取得Web.Config文件中的相关配置信息?
MSDN帮助:
1.System.Configuration 命名空间
ms-help://MS.MSDNQTR.2003FEB.2052/cpref/html/frlrfsystemconfiguration.htm
DataAccess项目
DataAccess项目中共4个类:Books类,Categories类,Customers类,Orders类.均实现了IDisposable接口。用来关闭活动的数据库连接。
这是MS提倡的一种释放非托管资源的Dispose模式。有关Dispose模式《.NET框架程序设计(修订本)》的19章“自动内存管理(垃圾收集)”有精采的论述.
类中通过调用存储过程,封装了对4个业务对象的Select,Insert,Update操作。
Select操作通过SqlDataAdapter的Fill方法填充对应的继承自DataSet的业务实体类,返回给调用者。Books类和Categories类只有Select操作.
Insert和Update操作通过一个private 函数返回InsertCommand或UpdateCommand对象。再于对外的的Public函数调用Private内部函数完成相应操作。Customers类中实现Insert,Update,Select操作,Orders类只有Insert操作。
在Customers类的LoadCustomerByEmail()方法中有对ApplicationAssert类的CheckCondition()方法调用
ApplicationAssert.CheckCondition(data.Tables[CustomerData.CUSTOMERS_TABLE].Rows.Count <= 1, "Integrity Failure: non-unique e-mail address", ApplicationAssert.LineNumber);
疑问:
1.数据访问层感觉实现了业务逻辑层的内容,平时如LoadCustomerByEmail()等方法都是写在业务逻辑层的。
2.是否有必要抽象出一个完全对数据库操作的基类,实现对数据库底层的操作?而不是在每个类如:Books,Customers中均一次次重写如SqlCommand对象,Dispose模式?