Enterprise Library—数据访问程序块

 

Enterprise Librar—数据访问程序块

前言

当我们在编写程序的时候,我们难免要对数据库进行访问,在进行数据库访问的时候,我们肯定会遇到下面的问题:

1)        重复代码——Writing (cutting and pasting) the same data access code throughout your data access layer

2)        硬编码——Matching stored procedure parameter definitions with the calling application code

3)        对连接池的担心——Wondering if your code is properly closing connections

4)        自己写组件简化对存储过程的调用——Writing a component to make it simpler to call stored procedures

5)        如何存储连接串——Wrestling with where/how to store connection string information

当然,这些问题我们自己也是可以解决的,但是数据访问程序块给我们提供了这些功能,我们为什么不用呢?

一、我们的目标

1)        一种简单有效的方法——A simple and efficient way of working with commonly used databases

2)        多种数据库之间的透明——Transparency when developing for multiple types of databases

3)        逻辑和物理数据库的“松耦合”——A way to place an indirection between a logical database instance and a physical database instance

4)        简单的校验方式——An easy way to adjust and validate the database configuration settings

二、Data Access Application Block能够做什么

1)        提供最佳实践–Provides access to the most often used features of ADO.NET with applied best practices

2)        改善一致性–Write code that works against multiple database brands(caveats apply!)

3)        改善安全性–Leverages the configuration application block to securely store connection strings

4)        改善易用性–Easily call a stored procedure with one line of code

三、设计Data Access Application Block

数据访问程序块要达到的目标:

1)        集成执行数据库访问的逻辑

2)        排除常见的代码错误,比如连接失败

3)        减轻开发者为常用的数据访问写同样的代码

4)        减少了一般代码的书写

5)        像.NET的数据访问架构向导一样,为数据访问集成最好的实践

6)        尽可能地使数据访问程序块的功能适用不同的数据库

数据访问程序块中,各个类之间的关系如下:

 

四、开始实践

终于知道数据访问数据块是做什么的了,废话少说,开始我们的旅程。

1)新建一个Windows或Web应用程序,将Microsoft.Practices.EnterpriseLibrary.Common.dll和Microsoft.Practices.EnterpriseLibrary.Data.dll引用到项目中。

2)把下面的命名空间增加到文件的头部using Microsoft.Practices.EnterpriseLibrary.Data

3)看看下面的一段代码:

 

None.gif     Database db  =   null ;
None.gif
None.gif    db 
=  DatabaseFactory.CreateDatabase( " QuickStarts Instance " );
None.gif
None.gif 
None.gif
None.gif    
int  count  =  ( int )db.ExecuteScalar(
None.gif
None.gif        CommandType.Text, 
None.gif
None.gif        
" SELECT COUNT(*) FROM Customers " );
None.gif
None.gif 
None.gif
None.gif    
string  message  =   string .Format(
None.gif
None.gif        
" There are {0} customers in the database " ,
None.gif
None.gif        count.ToString());
None.gif
None.gif 
None.gif
None.gifMessageBox.Show(message);
None.gif

 

(注:db.ExecuteScalar这个命令具有多态性,它和SqlCommand .ExecuteScalar返回的结果一样。db.ExecuteScalar方法的调用依赖与打开和关闭定义在配置文件中的数据库。)

4)再看一段代码

 

None.gif     Database db  =   null ;
None.gif
None.gif    db 
=  DatabaseFactory.CreateDatabase();
None.gif
None.gif 
None.gif
None.gif    DataSet ds 
=  db.ExecuteDataSet(
None.gif
None.gif        CommandType.Text,
None.gif
None.gif        
" SELECT * From Customers " );
None.gif
None.gif 
None.gif
None.gifdataGrid1.DataSource 
=  ds.Tables[ 0 ];
None.gif


(注:

db.ExecuteDataSet 方法依赖与打开和关闭连接,也返回 SQL 查询结果所填充的、可能包含多个表的程序集。这段代码中,我们没有指定 CreateDatabase 方法所创建的数据库实例。其实,在配置文件中有一个默认的数据库,它就是利用这个默认的数据库。)

5)再看看存储过程的运用

A.定义一个成员变量,它将在多个过程中使用

private Database _db = DatabaseFactory.CreateDatabase("QuickStarts Instance");

(注:看看这个成员变量的定义,它并不是创建一个数据库实例,只是一个对数据库的描绘)

B.执行存储过程

 

None.gif      using  (IDataReader dataReader  =  _db.ExecuteReader( " GetCategories " ))
None.gif
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif
InBlock.gif        
// Processing code 
InBlock.gif

InBlock.gif        
while (dataReader.Read())
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif
InBlock.gif            Category item 
= new Category(
InBlock.gif
InBlock.gif                dataReader.GetInt32(
0),
InBlock.gif
InBlock.gif                dataReader.GetString(
1),
InBlock.gif
InBlock.gif                dataReader.GetString(
2));
InBlock.gif
InBlock.gif            
this.cmbCategory.Items.Add(item);
InBlock.gif
ExpandedSubBlockEnd.gif        }

InBlock.gif
ExpandedBlockEnd.gif    }

None.gif


(注:在这里,你没有对数据库的连接做任何的管理,但是,释放

data reader 的返回值非常重要,这在上述的代码中完成。当 data reader 被释放, DbConnection 也被关闭。在 Database 类中有两种方法来返回数据集, ExecuteDataSet 和 LoadDataSet 。 ExecuteDataSet 返回一个新创建的数据集,而 LoadDataSet 是组装现有的一个。)

6)更新数据库

 

None.gif      //  TODO: Use the DataSet to update the Database 
None.gif

None.gif    System.Data.Common.DbCommand insertCommand 
=   null ;
None.gif
None.gif    insertCommand 
=  _db.GetStoredProcCommand( " HOLAddProduct " );
None.gif
None.gif    _db.AddInParameter(insertCommand, 
" ProductName "
None.gif
None.gif        DbType.String, 
" ProductName " , DataRowVersion.Current);
None.gif
None.gif    _db.AddInParameter(insertCommand, 
" CategoryID "
None.gif
None.gif        DbType.Int32, 
" CategoryID " , DataRowVersion.Current);
None.gif
None.gif    _db.AddInParameter(insertCommand, 
" UnitPrice "
None.gif
None.gif        DbType.Currency, 
" UnitPrice " , DataRowVersion.Current);
None.gif
None.gif 
None.gif
None.gif    System.Data.Common.DbCommand deleteCommand 
=   null ;
None.gif
None.gif    deleteCommand 
=  _db.GetStoredProcCommand( " HOLDeleteProduct " );
None.gif
None.gif    _db.AddInParameter(deleteCommand, 
" ProductID " ,
None.gif
None.gif        DbType.Int32, 
" ProductID " , DataRowVersion.Current);
None.gif
None.gif    _db.AddInParameter(deleteCommand, 
" LastUpdate "
None.gif
None.gif        DbType.DateTime, 
" LastUpdate " , DataRowVersion.Original);
None.gif
None.gif 
None.gif
None.gif    System.Data.Common.DbCommand updateCommand 
=   null ;
None.gif
None.gif    updateCommand 
=  _db.GetStoredProcCommand( " HOLUpdateProduct " );
None.gif
None.gif    _db.AddInParameter(updateCommand, 
" ProductID "
None.gif
None.gif        DbType.Int32, 
" ProductID " , DataRowVersion.Current);
None.gif
None.gif    _db.AddInParameter(updateCommand, 
" ProductName "
None.gif
None.gif        DbType.String, 
" ProductName " , DataRowVersion.Current);
None.gif
None.gif    _db.AddInParameter(updateCommand, 
" CategoryID "
None.gif
None.gif        DbType.Int32, 
" CategoryID " , DataRowVersion.Current);
None.gif
None.gif    _db.AddInParameter(updateCommand, 
" UnitPrice "
None.gif
None.gif        DbType.Currency, 
" UnitPrice " , DataRowVersion.Current);
None.gif
None.gif    _db.AddInParameter(updateCommand, 
" LastUpdate "
None.gif
None.gif        DbType.DateTime, 
" LastUpdate " , DataRowVersion.Current);
None.gif
None.gif 
None.gif
None.gif    
int  rowsAffected  =  _db.UpdateDataSet(
None.gif
None.gif        
this .dsProducts,
None.gif
None.gif        
" Products " ,
None.gif
None.gif        insertCommand,
None.gif
None.gif        updateCommand,
None.gif
None.gif        deleteCommand,
None.gif
None.gif        UpdateBehavior.Standard);
None.gif


(注:当我们更新数据库时,我们需要人工地创建存储过程的参数,需要知道

DataTable 的列和存储过程参数的映射。在这里 UpdateDataSet 方法,通过设置,可以获取数据流执行所有的更新事务。)

7)利用Enterprise Library Configuration来配置项目的配置文件

A.打开配置文件

如果你有定义在machine.config文件连接节,你会发现Enterprise Library Configuration工具会自动创建Data Access Application Block。

 

如果没有,你也可以自己创建一个,如下:

 


B.选择 the Data Access Application Block | Connection Strings | Connection String node. Change the Name property to QuickStarts Instance.

 


C.Select the Database node for this connection string. Change the Value property on the right hand side to EntLibQuickStarts.

 


D.选择 the Server node, and set its Value to "(local)\SQLEXPRESS".

 


E.Select the Data Access Application Block node. Set the DefaultDatabase property is to the QuickStarts Instance. Then, save it.

 



参考资料

Download Enterprise Library and related resources from:

http://msdn.microsoft.com/practices

http://msdn.microsoft.com/library/?url=/library/en-us/dnpag2/html/EntLib2.asp

Join the Enterprise Library Community at:

http://practices.gotdotnet.com/projects/entlib

Read blogs from the Enterprise Library team at:

http://msdn.microsoft.com/practices/Comm/EntLibBlogs/ 

转载于:https://www.cnblogs.com/mjgforever/archive/2006/07/03/441243.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值