系列回顾
在前面的文章中,我用了大量的篇幅对UDA及ORM的使用进行了讲解和演示,我们已经知道并熟悉的使用UDA和ORM构建简单的应用,AgileEAS.NET在应用的纵向结构上建议使用分层结构,提出独立数据层,数据层构成以ORM技术为基础、UDA技术做为辅助,共同完成这一系列功能。
基于接口开发
关于基于接口驱动的开发请参考DoNET企业架构应用-基于接口开发介绍以及应用场景和案例一文,在此不做具体介绍。
接口驱动的数据层
基于DoNET企业架构应用-基于接口开发介绍以及应用场景和案例一文所提出的观点,那么我们的数据层的结构将变成如下图所示:
也就是说数据层的消费者BL层或者UI层访问数据层依赖于DAL.Interface,而与具体的实现无关,基于这种理解的扩展,就是我们可以实现不同数据访问层实现的动态替换,如如某一个业务需要运行在基于SQLServer的数据库上,也需要运行的Oracle数据库之上,也可能需要运行在MySQL之上,因为不同数据库之间的细微差别,比如所使用的表名不同、数据库系统的函数、过程使用方式的差异,我们没有做到统一的数据访问层,那么我们就基于接口开发的思想把他分解成一个接口和三个实现。
在开发中如何进行
在AgileEAS.NET平台中我们提供了数据对象设计器,他能生成基于接口驱动的数据层解决方法,也就是说初始的数据层解决方案我们是可以使用工具生成,有关于数据对象设计器的介绍、使用请参考AgileEAS.NET平台之ORM设计器、AgileEAS.NET平台开发指南-数据层开发、AgileEAS.NET平台对象设计器使用帮助三篇文章,在生成的过程中默认的建议了一个接口层项目和一个实现层项目(根据设计时的数据库环境决定):
需要说明一点的是如果我们需要生成基于接口驱动的数据层,那么我们必须要选中项目选项卡上的是否生成接口层:
然后我们重新输出代码,并且把之前的业务代码迁移到新生成的代码之中,代码结构如下:
关键代码分析
在分析和介绍代码之前我有必要介绍一下演示解决方案中的项目依赖(引用关系):
数据层消费者项目ClassLib.OrmDemo依赖于数据接口层项目ClassLibDemo.DAL.Interface,而不依赖于具体的实现ClassLibDemo.DAL.SQLServer,而我们之前的案子是ClassLib.OrmDemo依赖于ClassLibDemo.DAL.SQLServer的。
首先我们来看看生成的接口层代码ClassLibDemo.DAL.Interface项目中的一个接口IDALManager:
1
///
<summary>
2
///
IDALManager接口,负责业务接口的实例化。
3
///
</summary>
4
public
interface
IDALManager
5
{
6
IProduct CreateProduct();
7
IProductList CreateProductList();
8
9
IProductIn CreateProductIn();
10
IProductInList CreateProductInList();
11
12
IProductStore CreateProductStore();
13
IProductStoreList CreateProductStoreList();
14
15
}
这个接口是一个与业务无关的接口,即不是我们定义的实体的抽像接口,而是一个抽像实现的实现化管理接口,即它管理干具体工作的实体接口的实例化,IDALManager在ClassLibDemo.DAL.SQLServer项目中有对应的实现DALManager:
1
///
<summary>
2
///
DALManager实现,负责业务接口的实例化。
3
///
</summary>
4
public
class
DALManager : IDALManager
5
{
6
public
IProduct CreateProduct()
7
{
8
return
new
Product();
9
}
10
11
public
IProductList CreateProductList()
12
{
13
return
new
ProductList();
14
}
15
16
public
IProductIn CreateProductIn()
17
{
18
return
new
ProductIn();
19
}
20
21
public
IProductInList CreateProductInList()
22
{
23
return
new
ProductInList();
24
}
25
26
public
IProductStore CreateProductStore()
27
{
28
return
new
ProductStore();
29
}
30
31
public
IProductStoreList CreateProductStoreList()
32
{
33
return
new
ProductStoreList();
34
}
35
}
那么IDALManager的实例化由谁负责呢,请看到ClassLibDemo.DAL.Interface项目中类DALHelper:
1
///
<summary>
2
///
IDALManager实例化过程。
3
///
</summary>
4
public
class
DALHelper
5
{
6
const
string
ConfigKey
=
"
ClassLibDemo.DAL
"
;
7
public
static
IDALManager DALManager
8
{
9
get
10
{
11
return
ContextHelper.GetContext().Container.GetComponentInstance(ConfigKey)
as
IDALManager;
12
}
13
}
14
}
DALHelper类中只有一个名称为DALManager的只读属性,返回AgileEAS.NET平台IOC容器中的一个名称为ClassLibDemo.DAL的对象,也就是IDALManager接口的实例化由DALHelper调用IOC容器来完成了IDALManager具体实现的动态挂载与延迟绑定,对象设计器为我们生成了以上模式的代码,根据代码我们需要在系统配置中增加如下的对象配置:
系统配置文件
1
<?
xml version="1.0" encoding="utf-8"
?>
2
<
configuration
>
3
<
configSections
>
4
<
section
name
="EAS.Objects"
type
="EAS.Objects.ConfigHandler,EAS.IOCContainer"
/>
5
</
configSections
>
6
<
EAS.Objects
>
7
<
object
name
="DataConnection"
assembly
="EAS.Data"
type
="EAS.Data.Access.SqlClientConnection"
LifestyleType
="Singleton"
>
8
<
property
name
="ConnectionString"
type
="string"
value
="Data Source=vm2003;Initial Catalog=eas;User ID=sa"
/>
9
</
object
>
10
<
object
name
="OrmAccessor"
assembly
="EAS.Data"
type
="EAS.Data.ORM.OrmAccessor"
LifestyleType
="Singleton"
>
11
<
property
name
="DbConnection"
type
="object"
value
="DataConnection"
/>
12
</
object
>
13
<!--
<object name="CacheAccessor" assembly="EAS.Data" type="EAS.Data.ORM.CacheAccessor" LifestyleType="Singleton">
14
</object>
-->
15
<
object
name
="DataAccessor"
assembly
="EAS.Data"
type
="EAS.Data.Access.SqlClientAccessor"
LifestyleType
="Singleton"
>
16
<
property
name
="Connection"
type
="object"
value
="DataConnection"
/>
17
</
object
>
18
<
object
name
="ClassLibDemo.DAL"
assembly
="ClassLibDemo.DAL.SQLServer"
type
="ClassLibDemo.DAL.SQLServer.DALManager"
LifestyleType
="Thread"
/>
19
</
EAS.Objects
>
20
</
configuration
>
至此为止,我们则可以在任何使用实体接口进行业务时采用如下的写法:
IProductList table = DALHelper.DALManager.CreateProductList();
消费者代码
当我们需要使用数据接口层中的某个接口进行业务操作的时间,我们需要使用DALHelper.DALManager的特定方法进行实现化抽像的数据层接口,我们只需要修改原有代码中的实体实例化过程的代码,我贴上ClassLib.OrmDemo项目中的ConditionDemo类的代码:
ConditionDemo
1
class
ConditionDemo
2
{
3
private
void
OutPut(IProductList table)
4
{
5
foreach
(IProduct product
in
table.Rows)
6
{
7
System.Console.WriteLine(
string
.Format(
"
Idn={0}\tCode={1}\tName={2}\tSpec={3}\tUnit={4}\tDescription={5}
"
, product.Idn, product.Code, product.Name, product.Spec, product.Unit, product.Description));
8
}
9
}
10
11
///
<summary>
12
///
查询单位为“1*瓶/瓶”的所有商品,并且按商品编码排序,演示EqualTo条件与排序条件。
13
///
</summary>
14
public
void
DemoCondition1()
15
{
16
IProductList table
=
DALHelper.DALManager.CreateProductList();
17
table.OrmAccessor
=
OrmContext.OrmAccessor;
18
table.GetProductListByUnit(
"
1*瓶/瓶
"
);
19
this
.OutPut(table);
20
}
21
22
///
<summary>
23
///
查询商品编码前1位为“1”的所有商品,并且按商品编码倒序排序。演示SQL条件的使用。
24
///
</summary>
25
public
void
DemoCondition2()
26
{
27
IProductList table
=
DALHelper.DALManager.CreateProductList();
28
table.OrmAccessor
=
OrmContext.OrmAccessor;
29
table.GetProductListByCode1(
"
1
"
);
30
this
.OutPut(table);
31
}
32
33
///
<summary>
34
///
查询商品编码前2位为“1a”的所有商品,不处理排序。演示Like条件的使用。
35
///
</summary>
36
public
void
DemoCondition3()
37
{
38
IProductList table
=
DALHelper.DALManager.CreateProductList();
39
table.OrmAccessor
=
OrmContext.OrmAccessor;
40
table.GetProductListByCode2(
"
1a
"
);
41
this
.OutPut(table);
42
}
43
44
///
<summary>
45
///
查询记录ID从100到500的记录,不处理排序。演示BetWeen条件的使用。
46
///
</summary>
47
public
void
DemoCondition4()
48
{
49
IProductList table
=
DALHelper.DALManager.CreateProductList();
50
table.OrmAccessor
=
OrmContext.OrmAccessor;
51
table.GetProductListByIDN(
100
,
500
);
52
this
.OutPut(table);
53
}
54
55
///
<summary>
56
///
查询记录ID从100到500并且编码前1位为“1”的所有商品记录,不处理排序。演示两个条件元素And组合的使用。
57
///
</summary>
58
public
void
DemoCondition5()
59
{
60
IProductList table
=
DALHelper.DALManager.CreateProductList();
61
table.OrmAccessor
=
OrmContext.OrmAccessor;
62
table.GetProductListByIDNAndCode(
100
,
500
,
"
1
"
);
63
this
.OutPut(table);
64
}
65
66
///
<summary>
67
///
查询记录ID从100到500并且编码前1位为“1”的所有商品记录以及商品编码前2位为“1a”并且单位为“1*瓶/瓶”的商品记录,不处理排序。演示两个条件Or组合的使用。
68
///
</summary>
69
public
void
DemoCondition6()
70
{
71
IProductList table
=
DALHelper.DALManager.CreateProductList();
72
table.OrmAccessor
=
OrmContext.OrmAccessor;
73
table.GetProductListByIDNOrCodeUnit(
100
,
500
,
"
1a
"
,
"
1*瓶/瓶
"
);
74
this
.OutPut(table);
75
}
76
}
按此方法修改ClassLib.OrmDemo中的其他代码,最后编译运行:
有关本例子所涉及的数据表结构请参考基于AgileEAS.NET平台基础类库进行应用开发-总体说明及数据定义一文,有关数据对象模型定义文件、文档、DDL脚本请下载:http://files.cnblogs.com/eastjade/demo.db.doc.sql.rar,本文代码下载:DAL.Demo1.rar。
链接
一步一步教你使用AgileEAS.NET基础类库进行应用开发-系列目录
AgileEAS.NET平台开发指南-系列目录
AgileEAS.NET应用开发平台介绍-文章索引
AgileEAS.NET平台应用开发教程-案例计划
AgileEAS.NET官方网站
敏捷软件工程实验室
QQ群:116773358