五. 项目的分层定义和编码规范
1. 数据 实体层的定义和编码规范
这一层主要定义类型化数据集的 XML 架构 (XSD) 。是数据库的内存表示,建立架构后代码由系统自动生成。
添加数据集:添加 à 添加新项 à 数据集;
定义数据表架构:
(1) 单表形式:从“服务器资源管理器”中将单表拖至设计界面,系统将自动生成表结构;
(2) 多表形式:
方法一 . 照上述方法生成多个表,然后手工添加表间关联(如果有的话) ;
方法二 . 照上述方法生成基本表,然后手工添加其他相关字段,组成一张表;
而他的 XML 格式这是这样的:
< xs:schema id ="AddressData" targetNamespace ="http://tempuri.org/AddressData.xsd" elementFormDefault ="qualified"
attributeFormDefault ="qualified" xmlns ="http://tempuri.org/AddressData.xsd" xmlns : mstns ="http://tempuri.org/AddressData.xsd"
xmlns : xs ="http://www.w3.org/2001/XMLSchema" xmlns : msdata ="urn:schemas-microsoft-com:xml-msdata">
< xs:element name ="AddressData" msdata : IsDataSet ="true">
< xs:complexType >
< xs:choice maxOccurs ="unbounded">
< xs:element name ="City">
< xs:complexType >
< xs:sequence >
< xs:element name ="CityID" msdata : ReadOnly ="true" msdata : AutoIncrement ="true" type ="xs:int" />
< xs:element name ="Abbr" type ="xs:string" />
< xs:element name ="NameGuid" msdata : DataType ="System.Guid, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
type ="xs:string" minOccurs ="0" />
< xs:element name ="ProvinceID" type ="xs:int" />
< xs:element name ="Remark" type ="xs:string" minOccurs ="0" />
< xs:element name ="Name" type ="xs:string" minOccurs ="0" /> ……
2. SQL 层的定义和编码规范
这一层定义用于与数据库交互的 SQL 语句。
这一层负责生成用于操作数据库的 SQL 语句。根据要操作的数据实体层来分别的定义这一层要实现的方法,在本项目组中,我们一般只需要定义选择查询所需要的 SQL 语句。
这里的方法中所做的工作全部是拼装出一个用于实现所需求的功能的 SQL 语句。如:
public static string strGetLogonLog = "SELECT LogonLog.* FROM LogonLog";
public static string GetLogonLogByUserName(string userName)
{
return strGetLogonLog
+ " WHERE (UserName = N'" +userName+ "')";
}
3. 数据访问层的定义和编码规范
这一层负责操作数据库。
这一层负责对数据库进行各种操作。根据要操作的数据实体层来分别的定义这一层要实现的方法,在本系统中,一般要包括读取数据的方法和将数据更新回数据库的方法。
在这一层向上,数据将可能有两个流向:如果本模块有商务规则,数据将流向商务规则层;如果本模块没有商务规则,则数据将流向商务界面层。
编码示例如下:
public MenuData GetMenu()
{
MenuData ds = new MenuData();
DatabaseExecute dbExec = new DatabaseExecute();
dbExec.GetData(ds.Menu,MenuSQL.strGetMenu);
return ds;
}
public void UpdateMenu(MenuData ds)
{
DataTableExtend dt = new DataTableExtend(ds.Menu,"Menu");
DatabaseExecute dbExec = new DatabaseExecute();
dbExec.ModifyDataBase(dt);
}
4. 商务规则层的定义和编码规范
商务规则层负责实现业务逻辑,根据不同的业务逻辑需求,会有不同的实现方式。
商务规则层的代码开发规范不再赘述,只提出以下几点要注意的地方:
所有的商务规则都在这一层实现。
对于计算字段要分清字段值得到的计算公式。
接口要尽量清晰。
举例如下:
public static ContractPaidListData CalculateFirstPaid(string contractGuid)
{
ContractS contractS = new ContractS();
ContractData.ContractRow contract = contractS.GetContractByGuid1(contractGuid).Contract[0];
ContractChargeDetailData contractChargeDetailDS = new ContractChargeDetailData();
ContractChargeDetailS contractChargeDetailS = new ContractChargeDetailS();
contractChargeDetailDS = contractChargeDetailS.GetContractChargeDetailByContractGuidAndOneFee(contractGuid);
foreach (ContractChargeDetailData.ContractChargeDetailRow contractCharge in contractChargeDetailDS.ContractChargeDetail)
{
decimal price;
int amount = 1;
if (!contractCharge.IsRealPriceNull())
{
price = contractCharge.RealPrice * amount;
}
else if (!contractCharge.IsDiscountNull())
{
price = contractCharge.StandardPrice *contractCharge.Discount/100 * amount;
}
else
{
price = contractCharge.StandardPrice * amount;
}
ContractPaidListData contractPaidDS = new ContractPaidListData();
……
5. 商务界面层的定义和编码规范
这一层提供界面和中间层的接口。
在这一层向下,数据将可能有两个流向:如果本模块有商务规则,数据将流向商务规则层;如果本模块没有商务规则,则数据将流向商务界面层。
这一层负责为界面层提供数据接口。根据要提供的接口功能分别的定义这一层要实现的方法,一般包括, InsertXXX( 数据集 ) 、 UpdateXXX( 数据集 ) 、 DeleteXXX( 数据集 ) 、 LoadXXX()( 用于返回一个数据集 ) 、 LoadXXXByXX( 字段 1 ,字段 2…)( 用于根据某个字段或多个字段来返回一个数据集 ) 。
这一层要做的工作很少,只是起一个定义接口和传递数据的工作。如果本模块有商务规则,则先实例化一个商务规则层中对应的类并调用其中相应的方法;如果本模块没有商务规则,则先实例化一个实体访问层种对应的类并调用其中相应的方法。
示例如下:
public SqlDataAdapter GetCountry()
{
try
{
CountryS countryS = new CountryS();
SqlDataAdapter m_Sql = countryS.GetCountry();
return m_Sql;
}
catch(Exception e)
{
throw e;
}
}
6. 界面层的定义和编码规范
界面层提供用户界面并处理用户操作。
这一层应尽量与后台分离,即,界面代码的作用应当主要是处理用户操作而不是业务逻辑的实现。其目的是为了将来方便的更换界面甚至更改平台,如从 C/S 转向 B/S 或者想反。
在这一成上得工作就是界面与数据实体的同步,如把数据显示到界面上或者把界面数据的更改同步回数据实体:
public void InitControl()
{
try
{
if (GetRequest() == null)
{
title.Text=" 新增: ";
this.SetTextNull();
btnDel.Visible = false;
}
else
{
title.Text=" 修改、删除: ";
btnSubmit.Value=" 确定修改 ";
btnReset.Visible=false;
CityData cityDS = new CityData();
CityF.GetCitiesByGuid(GetRequest()).Fill(cityDS.Cities);
CityData.City city = cityDS.Cities[0];
txtCityName.Text = city.CityName;
……
private void btnSubmit_ServerClick(object sender, System.EventArgs e)
{
try
{
if(!Page.IsValid)
{
this.ValidateMessage();
}
else
{
if (GetRequest() == null)
{
CityData cityDS = new CityData();
CityData.City city = cityDS.Cities.NewCity();
city.Guid = GUIDGenerator.GetNewGUID();
city.CityName = txtCityName.Text.Trim();
……
六. 项目各层暴露的接口
1. SQL 层的接口
这一层暴露的接口主要是为数据访问层提供的各种操作 SQL 语句,如用于各种方式的查询、新增、修改、删除的 SQL 等等。
对于传入方法中的参数, Get 方法传入一个或若干个需要用于查询的参数,为字符串值, Insert 、 Update 和 Delete 方法不传入任何参数;而对于返回值,所有的方法全部返回一个字符串。
例如:
public static **System.String ** DeleteCity ( )
public static **System.String ** GetCities ( )
public static **System.String ** GetCitiesByAbbr ( **System.String ** cityName )
public static **System.String ** InsertCity ( )
public static **System.String ** UpdateCity ( )
但在本项目组中,一般只需要写 Get 方法。
2. 数据访问层的接口
这一层暴露的接口则是供上层调用以对数据库做各种操作。
对于 Load 方法,首先获取数据库连接并打开,然后利用 SQL 定义层中定义的方法和刚才的数据库连接实例化一个 SqlDataAdapter 并将其作为返回值返回。返回前将数据连接关闭;
对于 Update 方法,首先获取数据库连接并打开,然后对类型化数据集中的数据进行操作。操作中,先利用 SQL 定义层中定义的方法和刚才的数据库连接实例化一个 SQLCommand ,然后将对应数据值赋给参数并执行 SQLCommand 。操作完成后返回操作是否成功的布尔值。返回前将数据连接关闭。
例如:
public static **System.Data.SqlClient.SqlDataAdapter ** GetCities ( )
public static **System.Data.SqlClient.SqlDataAdapter ** GetCitiesByAbbr ( **System.String ** cityName )
public static **System.Boolean ** UpdateCities ( **Capitalnet_MIS.Common.EntityDefinitions.CityData ** cityDS )
3. 商务规则层的接口
商务规则层的接口并没有一个统一的规范,根据实际需要而定。
例如:
public static **Capitalnet_MIS.Common.EntityDefinitions.ContractPaidListData ** CalculateContractAmount ( **System.DateTime ** date1 **, System.DateTime ** date2 **, System.Decimal ** total **, System.Decimal ** paidTotal **, System.Decimal ** unPaidTotal )
public static **Capitalnet_MIS.Common.EntityDefinitions.ContractPaidListData ** CalculateFirstPaid ( **System.String ** contractGuid )
4. 商务界面层的接口
这一层的接口很关键,因为这一层起一个连接界面层和中间层的作用。
对于传入方法中的参数, Get 方法传入一个或若干个需要用于查询的参数,为字符串值, Update 方法传入一个强类型的数据集;而对于返回值, Load 方法返回一个类型化的数据集, Update 方法返回一个布尔值。
例如:
public static **System.Data.SqlClient.SqlDataAdapter ** GetCities ( )
public static **System.Data.SqlClient.SqlDataAdapter ** GetCitiesByAbbr ( **System.String ** cityName )
public static **System.Boolean ** UpdateCities ( **Capitalnet_MIS.Common.EntityDefinitions.CityData ** cityDS )
七. 界面逻辑
界面逻辑如下图所示:
