幸福是一种心情、一种体会

认真学习,虚心向高手们请教

Enterprise LibraryV1.0-数据应用程序块


1、简介
数据应用程序块把我们从大量的机械的数据库访问代码中解放出来,同时给我们带来了在多个数据库甚至多个不同类型的数据库的中无缝切换的可能。
数据应用程序块的类继承层次非常简单,这里就不做详细介绍了(向看此文的朋友问个问题:为什么Vs.net2003的类视图窗口中很多类都不显示?)。
我们在我前面的配置应用程序块中提到过,要读取我们的自定义配置数据,首先要写一个配置数据类,数据应用程序块也不例外,这个类就是DatabaseSettings,其结构如下图:

从这个图里,我们可以看到DatabaseSettings主要包括3个集合类,DatabaseTypeData说明了配置的数据库类型,ConnectionStringData指明了每种数据库类型的连接串,InstanceData指明了当前的数据库实例。
2、使用说明
使用时分两步:先用配置控制台添加数据应用程序块,再在程序中写代码。
⑴用配置控制台添加数据应用程序块
①添加数据应用程序块,之后是分别设置应用程序要访问的数据库类型、每个类型的数据库即连接串和当前的默认数据库。
②添加应用程序要访问的数据库类型(Database Types),如SQL Server、Oracle、Sybase、Access等
③设置每个数据库的连接串。添加上相应的连接参数。
④设定默认的数据库及其连接串。
⑤设置完毕,保存。
⑵写数据访问代码
数据应用程序块支持我们常见的大部分功能:执行SQL文本,执行存储过程、启用事务、离线处理、批量更新等等,下面我们分别举例说明。
①执行SQL语句
Database db = DatabaseFactory.CreateDatabase();
string sql = "SELECT * FROM [AddressList]";
DBCommandWrapper cmdWrapper = db.GetSqlStringCommandWrapper(sql);
return db.ExecuteDataSet(cmdWrapper);
②执行存储过程
Database db = DatabaseFactory.CreateDatabase();

string sqlCommand = "GetUserById";
DBCommandWrapper cmd = db.GetStoredProcCommandWrapper(sqlCommand);
cmd.AddInParameter("@UserId", DbType.Int32, 1);
Literal1.Text = (string)db.ExecuteScalar(cmd);
③启用事务
Database db = DatabaseFactory.CreateDatabase();
string sqlCommand = "CreditAccount";
DBCommandWrapper creditCommandWrapper = db.GetStoredProcCommandWrapper(sqlCommand);
sqlCommand = "DebitAccount";
DBCommandWrapper debitCommandWrapper = db.GetStoredProcCommandWrapper(sqlCommand);
using (IDbConnection connection = db.GetConnection())//
{
 connection.Open();
 IDbTransaction transaction = connection.BeginTransaction();
 try
 {
  db.ExecuteNonQuery(creditCommandWrapper, transaction);
  db.ExecuteNonQuery(debitCommandWrapper, transaction);
  transaction.Commit();
  result = true;
 }
 catch
 {
  transaction.Rollback();
 }
 connection.Close();
 return result;
}
④批量更新
Database db = DatabaseFactory.CreateDatabase();
DataSet productsDataSet = new DataSet();
string sqlCommand = "Select ProductID, ProductName, CategoryID, UnitPrice, LastUpdate From Products";
DBCommandWrapper dbCommandWrapper = db.GetSqlStringCommandWrapper(sqlCommand);
string productsTable = "Products";

db.LoadDataSet(dbCommandWrapper, productsDataSet, productsTable);

DataTable table = productsDataSet.Tables[productsTable];
DataRow addedRow = table.Rows.Add(new object[] {DBNull.Value, "New product", 11, 25});
table.Rows[0]["ProductName"] = "Modified product";

DBCommandWrapper insertCommandWrapper = db.GetStoredProcCommandWrapper("AddProduct");
insertCommandWrapper.AddInParameter("@ProductName", DbType.String, "ProductName", DataRowVersion.Current);
insertCommandWrapper.AddInParameter("@CategoryID", DbType.Int32, "CategoryID", DataRowVersion.Current);
insertCommandWrapper.AddInParameter("@UnitPrice", DbType.Currency, "UnitPrice", DataRowVersion.Current);

DBCommandWrapper deleteCommandWrapper = db.GetStoredProcCommandWrapper("DeleteProduct");
deleteCommandWrapper.AddInParameter("@ProductID", DbType.Int32, "ProductID", DataRowVersion.Current);

DBCommandWrapper updateCommandWrapper = db.GetStoredProcCommandWrapper("UpdateProduct");
updateCommandWrapper.AddInParameter("@ProductID", DbType.Int32, "ProductID", DataRowVersion.Current);
updateCommandWrapper.AddInParameter("@ProductName", DbType.String, "ProductName", DataRowVersion.Current);
updateCommandWrapper.AddInParameter("@LastUpdate", DbType.DateTime, "LastUpdate", DataRowVersion.Current);

int rowsAffected = db.UpdateDataSet(productsDataSet, "Products", insertCommandWrapper, updateCommandWrapper,
deleteCommandWrapper, UpdateBehavior.Standard);
这里的代码来源于Quick Start,这里需要注意的就是DataRowVersion.Current,批量更新时根据具体情况选择其值。同时ExecuteScalar、UpdateDataSet等方法重载好几个不同的方法原型,您可以根据具体情况选择。
⑶注意的问题
这里需要注意的就是在执行存储过程时,有两个获取IDbCommand对象的方法:
public abstract DBCommandWrapper GetStoredProcCommandWrapper(string storedProcedureName);
public abstract DBCommandWrapper GetStoredProcCommandWrapper(string storedProcedureName, params object[] parameterValues);
如果你要缓存参数,就用第二个方法,不缓存参数就用第一个方法(不知我说的对不对?),因为在准备IDbCommand对象时,有下面的语句,
if (command.IsFurtherPreparationNeeded())
{
      parameterCache.FillParameters(command, ParameterToken);
}
这样,在用第二个方法时,会从缓存中取参数,当你多次调用同一存储过程时,可以考虑用用第二个方法,当然,如果有必要可以缓存执行的结果,性能更佳,这将用到缓存应用程序块。

还需要提一句,就是对于保存在配置文件中的数据库信息,我们也是可以加密的,方法与配置应用程序块的加密方式一致。可以看我关于配置应用程序块的使用方法说明。每个应用程序块的配置数据都是可以加密保存的。

有人已经制作了使用数据应用程序块的模板,比较不错:http://cstemplates.sourceforge.net

posted on 2005-08-04 22:30 生活、工作 阅读(4874) 评论(8)  编辑 收藏

评论

#1楼  2005-09-07 21:12 Cure      

楼主提到的模板不错,更重要的是还包括测试代码,对数据库操作的单元测试一直是个比较头痛的问题,正好可以看看,学习!   回复  引用  查看    

#2楼  2005-09-23 13:43 高巍      

想请教以下,用这个模块来访问数据,好象性能下降很多,读一个很小的表格竟然要2秒左右才显示(不是机器差,赛样2.2 256m),是什么原因?谢谢   回复  引用  查看    

#3楼 [楼主] 2005-09-25 21:09 生活、工作      

反射的原因,初次运行较慢。   回复  引用  查看    

#4楼  2005-10-18 22:30 Voyages [未注册用户]

netTiers还是不错的,但自定义方法还是有点问题,自己写的存贮过程只返回单值还是会被netTiers把生成的方法写成void的
The stored procedure to method convertion follow these rules for the method return type:

if sp rowset == table rowset then method return an EntityCollection
if sp rowset == one value (ex: int, varchar, etc.) then method return a scalar value
if other rowset then method return void
怎样才算单值呢,存贮过程return一个output 参数还不算是吗?
  回复  引用  查看    

#5楼  2005-11-29 21:22 凌风_314 [未注册用户]

我在使用数据应用程序块时,出现了异常。不知道该怎么解决,求教。
如下:

安全性异常
说明: 应用程序试图执行安全策略不允许的操作。要授予此应用程序所需的权限,请与系统管理员联系,或在配置文件中更改该应用程序的信任级别。

异常详细信息: System.Security.SecurityException: 不允许所请求的注册表访问权。
  回复  引用  查看    

#6楼 [楼主] 2005-11-30 22:08 生活、工作      

to 凌风_314:
保证InstallServices.bat正确运行,如果有问题,就分析一下这个批处理文件,使之正确运行。   回复  引用  查看    

#7楼  2006-04-06 09:14 蛙蛙池塘      

凌风的那个问题我也遇到过,我是重新编译了Common来解决的。
关于自定义方法,我们可以扩展nettiers生成的数据访问类,自己写存储过程让UI调用,我已经试过了,自己扩展的代码不会被下次覆盖。   回复  引用  查看    

#8楼  2007-07-11 11:56 yfshg [未注册用户]

连接字符串的用户名,密码再在那里设置啊?   回复  引用  查看    


标题  
姓名  
主页
Email (只有博主才能看到) 
验证码 *  看不清,换一张
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
该文被作者在 2005-08-05 08:46 编辑过
 
另存  打印
最新IT新闻: