Enterprise Library 数据访问应用程序块快速入门
本文档维护在:http://wiki.entlib.net.cn/EntlibHelp31DataAccessApplicationBlock.ashx。
Enterprise Library 快速入门是简单的、易于理解的应用程序块关键特性的示例,使用了一个实现了常规场景的漫游集合来说明这些特性。漫游是常见场景的实现。
如果要理解一个应用程序块,快速入门将是理想的起始点,并且用试验源代码来学习新的技术也是非常舒服的。如果已对 .NET 框架比较熟悉,以及如果要查看简单的、有助于理解如何解决特定问题的代码示例的话,它们将是非常好的资源。
要使用快速入门的所有优点的话,将需要熟悉面向对象编程相关的概念和技术。
此快速入门被配置为运行在 SQL Server 数据库实例下,用于创建需要的 SQL 数据库的 SQL 脚本被提供在本地计算机上。
快速入门有下列特性:
系统需求
要构建和运行快速入门,需要下列环境:
快 速入门的源代码已与数据访问应用程序块一起安装。但是,在使用应用程序之前,首先运行 SetupQuickStartsDB.bat ,它被放在数据访问快速入门的根目录下。此批处理文件假设本地 SQL Server 有着 (local)"SQLEXPRESS 的实例名。它创建一个名为 EntLibQuickStarts 的 SQL Server 数据库。如果要使用不同的 SQL Server 或者不同的服务器,就必须要手工更新脚本,脚本假设了下面的设置:
构建和运行快速入门
快速入门是源代码形式的,这就意味着在运行它之前必须编译它。可以使用 Visual Studio 来构建快速入门。
构建数据访问快速入门
快速入门的配置
数据访问快速入门中的漫游带有已定义的配置,它包含在 App.config 文件中。此文件被放置在与快速入门项目文件同样的文件夹中,并有下列设置:
要修改或查看这些设置,使用 Enterprise Library 配置控制台打开在包含快速入门项目文件文件夹下的 App.config 文件。App.config 文件包含配置数据。
每次构建代码时,Visual Studio 都会复制 App.config 文件到项目的输出目录中(创建快速入门可执行文件的目录中),并更名为 DataAccessQuickStart.exe.config 。
这 意味着如何要使用配置控制台修改任何配置设置,如到期周期,并且计划重新构建解决方案,就必须通过打开在快速入门源代码目录中的 App.config 文件来修改设置。也可以用配置控制台打开 DataAccessQuickStart.exe.config 文件,然后修改应用程序配置。然而,这些修改会在下一次成功构建期间被覆盖。
重建示例
1. 配置数据库,对于必须的步骤,请参见数据访问快速入门中的“快速入门的配置”。 2. 创建一个名为 GetProductsInCategory 的方法,方法接受一个作为整数参数的类别标识,并返回一个 DataSet 。添加下列代码在此方法中。
3. 通过添加下列的代码创建 database 。工厂创建了一个拥有默认配置的 Database 对象。
4. 通过添加下列代码创建一个 command 。此代码创建了一个与存储过程一起使用的 DbCommand 对象。在这种情况下,代码调用 GetProductsByCategory 。DbCommand 使用一个输入参数,CategoryID。
5. 声明 DataSet ,它将通过 ExecuteDataSet 的调用创建。
6. 通过调用下列代码调用 ExecuteDataSet 。ExecuteDataSet 传递 DbCommand 对象,它指明 GetProductsByCategory 将组装 DataSet 。
7. 返回结果到用户接口代码。用户接口可以通过添加下列代码来处理结果,它绑定返回的 DataSet 到 DataGrid 。
重建示例
1. 配置数据库。对于必要步骤,请参见数据访问快速入门中的“快速入门配置”。
2. 通过添加下列代码来创建 database 。工厂创建了一个拥有默认配置的 Database 对象。
3. 通过添加下列代码创建 command ,它创建了一个与 SQL 字符串一起使用的 DbCommand 对象。
4. 参数添加下列代码调用 ExecuteReader ,它为使用的 SQL 命令文本传递 DbCommand 来组装 DbDataReader。
5. 通过在 using 语句中添加下列代码来处理结果,它循环处理 DbDataReader ,并将结果放到一个字符串中。
6. 如果 DbDataReader 没有被包含在 using 语句中,添加下列的代码来显式的关闭 DbDataReader 。
重建示例
1. 配置数据库。对于必要的步骤,请参见数据访问快速入门中的“快速入门的配置”。
2. 参数添加下列代码创建 database 。工厂创建了拥有默认配置的 SqlDatabase 对象。
3. 通过添加下列代码创建 command 。它使用 SQL 字符串创建了一个 DbCommand 。
4. 调用 ExecuteXmlReader ,然后添加下列代码来处理结果。
5. 通过添加下列代码来关闭 XmlReader 和 Connection 。
重建示例
1. 配置数据库。对于必要的步骤,请参见数据访问快速入门中的“快速入门配置”。
2. 通过添加下列代码创建数据库。工厂创建了拥有默认配置的 Database 对象。
3. 通过添加下列代码创建一个命令。它创建了一个与存储过程一起使用的 DbCommand 。在这里,它是 GetProductDetails,它有一个输入参数:ProductID,并将结果返回到二个输出参数中:ProductName 和 UnitPrice。
4. 通过添加下列代码调用 ExecuteNonQuery 。它传递 DbCommand ,指明 GetProductsByCategoryDetails 存储过程将组装输出参数。
5. 通过添加下列代码来处理结果,它将保存在输出参数中的值放到一个字符串中。
使用提示
ExecuteNonQuery 方法返回的行数受查询的影响(典型的是 Insert、 Update 或者 Delete 操作)。在上面的代码示例中,返回值被忽略。
重建示例
1. 配置数据库。对于必要的步骤,请参见数据访问快速入门中的“快速入门配置”。
2. 通过添加下列代码创建数据库。工厂创建了一个拥有默认配置的 Database 对象。
3. 通过添加下列代码创建命令。它创建了一个与存储过程一起使用的 DbCommand 。在这里,它是 GetProductName 。它有一个输入参数:ProductID,并返回产品的名称做为结果。
4. 调用 ExecuteScalar,并传递 DbCommand,指明 GetProductName 存储过程将获取产品的名称。
使用提示
在使用一个命令访问单个条目时考虑下面几点:
重建示例
1. 配置数据库。对于必要的步骤,请参见数据访问快速入门中的“快速入门的配置”。
2. 通过添加下列代码创建数据库。工厂创建了一个拥有默认配置的 Database 对象。
3. 通过添加下列代码创建命令。它创建了与存储过程一起使用的 DbCommand 。在此,它们是 CreditAccount 和 DebitAccount 。每个存储过程都有一个输入参数:AccountID 和 Amount。
4. 下列代码展示了如何启动一个事务,然后决定是否提交它,或者如果发生错误时,执行回滚。
重建示例
1. 配置数据库。对于必要的步骤,请参见数据访问快速入门中的“快速入门的配置”。
2. 通过添加下列代码创建数据库。工厂通过使用默认配置创建 Database 对象。
3. 通过添加下列代码获取初始 DataSet。
4. 通过添加下列代码修改 DataSet。
5. 下列代码展示了如何创建插入新的产品的 DbCommand 对象、删除一个产品,并更新在 DataSet 中的数据。
6. 通过添加下列代码提交 DataSet ,它展示了如何使用缓存在 DataSet 中的本地数据更新数据库。
Enterprise Library 快速入门是简单的、易于理解的应用程序块关键特性的示例,使用了一个实现了常规场景的漫游集合来说明这些特性。漫游是常见场景的实现。
如果要理解一个应用程序块,快速入门将是理想的起始点,并且用试验源代码来学习新的技术也是非常舒服的。如果已对 .NET 框架比较熟悉,以及如果要查看简单的、有助于理解如何解决特定问题的代码示例的话,它们将是非常好的资源。
要使用快速入门的所有优点的话,将需要熟悉面向对象编程相关的概念和技术。
8.1 - 数据访问应用程序块快速入门
数据访问快速入门应用程序示范了数据访问应用程序块的某些关键特性。它使用一个漫游集来示范这些特性,漫游是在关键场景中讨论的情况的实现。漫游对如下场景进行了说明:- 使用 DataSet 获取多行数据
- 使用 DbDataReader 获取多行数据
- 获取多行数据为 XML
- 执行命令并访问输出参数中的结果
- 执行命令并访问单项结果
- 在一个事务中执行多个更新
- 使用 DataSet 更新数据库
此快速入门被配置为运行在 SQL Server 数据库实例下,用于创建需要的 SQL 数据库的 SQL 脚本被提供在本地计算机上。
快速入门有下列特性:
- 场景相互独立,所以可以以任何顺序查看它们。每个场景都包含了所有完成场景所需要的数据访问代码。
- 访问数据库的代码包含在自己的类中,与快速入门的 form 分离。在此类不是真正的数据层时,它单独示范了独立于用户接口代码的数据访问代码。
- 一个顶层处理程序捕获了所有在任何场景中出现的异常。处理程序显示了一个展示异常消息以及在运行快速入门前运行的安装脚本:SetupQuickStartsDB.bat 的提示的对话框。
- 在快速入门的左边面板中的每个按钮都对应一个在关键场景中讨论的场景。单击 View Walkthrough 按钮显示适当的帮助文件。Quit 按钮用于停止应用程序。
系统需求
要构建和运行快速入门,需要下列环境:
- Microsoft Windows 2000, Windows XP Professional, 或 Windows Server 2003 操作系统
- Microsoft .NET Framework, version 2.0
- Microsoft Visual Studio 2005 开发系统
- 运行 SQL Server 7.0 或更高版本的数据库服务器
快 速入门的源代码已与数据访问应用程序块一起安装。但是,在使用应用程序之前,首先运行 SetupQuickStartsDB.bat ,它被放在数据访问快速入门的根目录下。此批处理文件假设本地 SQL Server 有着 (local)"SQLEXPRESS 的实例名。它创建一个名为 EntLibQuickStarts 的 SQL Server 数据库。如果要使用不同的 SQL Server 或者不同的服务器,就必须要手工更新脚本,脚本假设了下面的设置:
Server: (local)"SQLEXPRESS
Authentication: integrated
注意:要成功的运行脚本,必须有创建 SQL Server 数据库的充分权限。
构建和运行快速入门
快速入门是源代码形式的,这就意味着在运行它之前必须编译它。可以使用 Visual Studio 来构建快速入门。
构建数据访问快速入门
- 确认 Enterprise Library 源代码已安装;
- 从 Windows 资源管理器中打开 Enterprise Library 源代码文件夹,或者从开始菜单快捷方式打开:在任务栏上,单击开始,指向程序,指向 Microsoft patterns and practices ,指向 Enterprise Library 3.1 – May 2007 ,然后选择 Enterprise Library 3.1 Source Folder。
- 打开 QuickStarts ,然后是 Data ,再然后是 CS(用于 C# )或者 VB (用于 Visual Basic .NET )
- 双击 DataAccessQuickStart.sln 图标。
- Visual Studio 打开,显示解决方案文件。在菜单中,单击生成。
- 单击重新生成解决方案,默认情况下,这是调试生成。
- 按 F5 运行快速入门。
快速入门的配置
数据访问快速入门中的漫游带有已定义的配置,它包含在 App.config 文件中。此文件被放置在与快速入门项目文件同样的文件夹中,并有下列设置:
- 数据库类型为 SQL Server 。
- 服务器的名称是 (local)"SQLEXPRESS。
- 数据库的名称是 EntLibQuickStarts。
- 连接字符串的名称是 DataAccessQuickStart。
- 集成安全设置是 SSPI。
要修改或查看这些设置,使用 Enterprise Library 配置控制台打开在包含快速入门项目文件文件夹下的 App.config 文件。App.config 文件包含配置数据。
每次构建代码时,Visual Studio 都会复制 App.config 文件到项目的输出目录中(创建快速入门可执行文件的目录中),并更名为 DataAccessQuickStart.exe.config 。
这 意味着如何要使用配置控制台修改任何配置设置,如到期周期,并且计划重新构建解决方案,就必须通过打开在快速入门源代码目录中的 App.config 文件来修改设置。也可以用配置控制台打开 DataAccessQuickStart.exe.config 文件,然后修改应用程序配置。然而,这些修改会在下一次成功构建期间被覆盖。
8.1.1 - 漫游:使用 DataSet 获取多行
此漫游示范了如何使用 DataSet 获取多行数据,它假设下列存储过程已被创建在代码中提到的连接字符串所对应的数据库中。CREATE Procedure GetProductsByCategory
(
@CategoryID int
)
AS
SELECT ProductID, ProductName, CategoryID, UnitPrice, LastUpdate
FROM Products
WHERE CategoryID = @CategoryID
重建示例
1. 配置数据库,对于必须的步骤,请参见数据访问快速入门中的“快速入门的配置”。 2. 创建一个名为 GetProductsInCategory 的方法,方法接受一个作为整数参数的类别标识,并返回一个 DataSet 。添加下列代码在此方法中。
C#
public DataSet GetProductsInCategory(int Category)
{
}
Visual Basic
Public Function GetProductsInCategory(ByRef Category As Integer) As DataSet
End Function
3. 通过添加下列的代码创建 database 。工厂创建了一个拥有默认配置的 Database 对象。
C#
Database db = DatabaseFactory.CreateDatabase();
Visual Basic
Dim db As Database = DatabaseFactory.CreateDatabase()
4. 通过添加下列代码创建一个 command 。此代码创建了一个与存储过程一起使用的 DbCommand 对象。在这种情况下,代码调用 GetProductsByCategory 。DbCommand 使用一个输入参数,CategoryID。
C#
string sqlCommand = "GetProductsByCategory";
DbCommand dbCommand = db.GetStoredProcCommand(sqlCommand);
db.AddInParameter(dbCommand, "CategoryID", DbType.Int32, Category);
Visual Basic
Dim sqlCommand As String = "GetProductsByCategory"
Dim dbCommand As DbCommand = db.GetStoredProcCommand(sqlCommand)
db.AddInParameter(dbCommand, "CategoryID", DbType.Int32, Category)
5. 声明 DataSet ,它将通过 ExecuteDataSet 的调用创建。
C#
// DataSet that will hold the returned results.
DataSet productDataSet = null;
Visual Basic
' DataSet that will hold the returned results.
Dim productDataSet As DataSet = Nothing
6. 通过调用下列代码调用 ExecuteDataSet 。ExecuteDataSet 传递 DbCommand 对象,它指明 GetProductsByCategory 将组装 DataSet 。
C#
productDataSet = db.ExecuteDataSet(dbCommand);
Visual Basic
productDataSet = db.ExecuteDataSet(dbCommand)
7. 返回结果到用户接口代码。用户接口可以通过添加下列代码来处理结果,它绑定返回的 DataSet 到 DataGrid 。
C#
resultsDataGrid.SetDataBinding(productDataSet, "Table");
Visual Basic
resultsDataGrid.SetDataBinding(productDataSet, "Table")
8.1.2 - 漫游:使用 DbDataReader 获取多行数据
此漫游示范了如何使用 DbDataReader 获取多行数据。重建示例
1. 配置数据库。对于必要步骤,请参见数据访问快速入门中的“快速入门配置”。
2. 通过添加下列代码来创建 database 。工厂创建了一个拥有默认配置的 Database 对象。
C#
db = DatabaseFactory.CreateDatabase();
Visual Basic
db = DatabaseFactory.CreateDatabase()
3. 通过添加下列代码创建 command ,它创建了一个与 SQL 字符串一起使用的 DbCommand 对象。
C#
string sqlCommand = "Select CustomerID, Name, Address, City, Country, PostalCode " +
"From Customers";
DbCommand dbCommand = db.GetSqlStringCommand(sqlCommand);
Visual Basic
Dim sqlCommand As String = "Select CustomerID, Name, Address, City, Country, PostalCode " & _
"From Customers"
Dim dbCommand As DbCommand = db.GetSqlStringCommand(sqlCommand)
4. 参数添加下列代码调用 ExecuteReader ,它为使用的 SQL 命令文本传递 DbCommand 来组装 DbDataReader。
C#
using (IDataReader dataReader = db.ExecuteReader(dbCommand))
{
// Processing code
}
Visual Basic
Using dataReader As IDataReader = db.ExecuteReader(dbCommand)
' Processing code
End Using
5. 通过在 using 语句中添加下列代码来处理结果,它循环处理 DbDataReader ,并将结果放到一个字符串中。
C#
StringBuilder readerData = new StringBuilder();
while (dataReader.Read())
{
// Get the value of the Name column in the DbDataReader.
readerData.Append(dataReader"Name");
readerData.Append(Environment.NewLine);
}
Visual Basic
Dim readerData As StringBuilder = New StringBuilder()
While (dataReader.Read())
' Get the value of the Name column in the DbDataReader.
readerData.Append(dataReader("Name"))
readerData.Append(Environment.NewLine)
End While
6. 如果 DbDataReader 没有被包含在 using 语句中,添加下列的代码来显式的关闭 DbDataReader 。
C#
// Close the reader, which will cause the connection to be closed as well.
if (dataReader != null)
dataReader.Close();
Visual Basic
' Close the reader, which will cause the connection to be closed as well.
If (Not dataReader Is Nothing) Then
dataReader.Close()
End If
8.1.3 - 漫游:获取多行 XML 数据
此漫游示范了如何从 SQL Server 数据库中获取 XML 数据。重建示例
1. 配置数据库。对于必要的步骤,请参见数据访问快速入门中的“快速入门的配置”。
2. 参数添加下列代码创建 database 。工厂创建了拥有默认配置的 SqlDatabase 对象。
C#
SqlDatabase dbSQL = DatabaseFactory.CreateDatabase() as SqlDatabase;
Visual Basic
Dim dbSQL As SqlDatabase = DirectCast(DatabaseFactory.CreateDatabase(), SqlDatabase)
3. 通过添加下列代码创建 command 。它使用 SQL 字符串创建了一个 DbCommand 。
C#
string sqlCommand = "Select ProductID, ProductName, CategoryID, UnitPrice, LastUpdate " +
"From Products FOR XML AUTO";
DbCommand dbCommand = dbSQL.GetSqlStringCommand(sqlCommand);
Visual Basic
Dim sqlCommand As String = "Select ProductID, ProductName, CategoryID, UnitPrice, LastUpdate " & _
"From Products FOR XML AUTO"
Dim dbCommand As DbCommand = dbSQL.GetSqlStringCommand(sqlCommand)
4. 调用 ExecuteXmlReader ,然后添加下列代码来处理结果。
C#
XmlReader productsReader = null;
StringBuilder productList = new StringBuilder();
try
{
productsReader = dbSQL.ExecuteXmlReader(dbCommand);
while (!productsReader.EOF)
{
if (productsReader.IsStartElement())
{
productList.Append(productsReader.ReadOuterXml());
productList.Append(Environment.NewLine);
}
}
}
Visual Basic
Dim productsReader As XmlReader = Nothing
Dim productList As StringBuilder = New StringBuilder()
Try
productsReader = dbSQL.ExecuteXmlReader(dbCommand)
While (Not productsReader.EOF)
If (productsReader.IsStartElement()) Then
productList.Append(productsReader.ReadOuterXml())
productList.Append(Environment.NewLine)
End If
End While
5. 通过添加下列代码来关闭 XmlReader 和 Connection 。
C#
finally
{
// Close the Reader.
if (productsReader != null)
{
productsReader.Close();
}
// Explicitly close the connection. The connection is not closed
// when the XmlReader is closed.
if (dbComman.Connection != null)
{
dbCommand.Connection.Close();
}
}
Visual Basic
Finally
' Close the Reader.
If (Not productsReader Is Nothing) Then
productsReader.Close()
End If
' Explicitly close the connection. The connection is not closed
' when the XmlReader is closed.
If (Not dbCommand.Connection Is Nothing) Then
dbCommand.Connection.Close()
End If
End Try
8.1.4 - 漫游:运行一个 Command 并访问输出参数
本漫游示范了如何通过执行一条 SQL 命令并获取输出参数来从单个行中获取多个值。它假定下列存储过程已被创建在代码中涉及的连接字符串所对应的数据库中。CREATE PROCEDURE GetProductDetails
@ProductID int,
@ProductName nvarchar(40) OUTPUT,
@UnitPrice money OUTPUT,
@QtyPerUnit nvarchar(20) OUTPUT
AS
SELECT @ProductName = ProductName,
@UnitPrice = UnitPrice,
@QtyPerUnit = QuantityPerUnit
FROM Products
WHERE ProductID = @ProductID
重建示例
1. 配置数据库。对于必要的步骤,请参见数据访问快速入门中的“快速入门配置”。
2. 通过添加下列代码创建数据库。工厂创建了拥有默认配置的 Database 对象。
C#
Database db = DatabaseFactory.CreateDatabase();
Visual Basic
Dim db As Database = DatabaseFactory.CreateDatabase()
3. 通过添加下列代码创建一个命令。它创建了一个与存储过程一起使用的 DbCommand 。在这里,它是 GetProductDetails,它有一个输入参数:ProductID,并将结果返回到二个输出参数中:ProductName 和 UnitPrice。
C#
string sqlCommand = "GetProductsDetails";
DbCommand dbCommand = db.GetStoredProcCommand(sqlCommand);
db.AddInParameter(dbCommand, "ProductID", DbType.Int32, productID);
// Output parameters specify the size of the return data.
db.AddOutParameter(dbCommand, "ProductName", DbType.String, 50);
db.AddOutParameter(dbCommand, "UnitPrice", DbType.Currency, 8);
Visual Basic
Dim sqlCommand As String = "GetProductDetails"
Dim dbCommand As DbCommand = db.GetStoredProcCommand(sqlCommand)
db.AddInParameter(dbCommand, "ProductID", DbType.Int32, productID)
' Output parameters specify the size of the return data.
db.AddOutParameter(dbCommand, "ProductName", DbType.String, 50)
db.AddOutParameter(dbCommand, "UnitPrice", DbType.Currency, 8)
4. 通过添加下列代码调用 ExecuteNonQuery 。它传递 DbCommand ,指明 GetProductsByCategoryDetails 存储过程将组装输出参数。
C#
db.ExecuteNonQuery(dbCommand);
Visual Basic
db.ExecuteNonQuery(dbCommand)
5. 通过添加下列代码来处理结果,它将保存在输出参数中的值放到一个字符串中。
C#
string results = string.Format(CultureInfo.CurrentCulture, "{0}, {1}, {2:C} ",
db.GetParameterValue(dbCommand, "@ProductID"),
db.GetParameterValue(dbCommand, "@ProductName"),
db.GetParameterValue(dbCommand, "@UnitPrice"));
Visual Basic
Dim results As String = String.Format(CultureInfo.CurrentCulture, "{0}, {1}, {2:C} ", _
db.GetParameterValue(dbCommand, "@ProductID"), _
db.GetParameterValue(dbCommand, "@ProductName"), _
db.GetParameterValue(dbCommand, "@UnitPrice"))
使用提示
ExecuteNonQuery 方法返回的行数受查询的影响(典型的是 Insert、 Update 或者 Delete 操作)。在上面的代码示例中,返回值被忽略。
8.1.5 - 漫游:运行一个 Command 并访问单项结果
本漫游示范了如何获取单个条目。它假定下列存储过程已创建在代码中所涉及的连接字符串所对应的数据库中。CREATE PROCEDURE GetProductName
@ProductID int
AS
SELECT ProductName
FROM Products
WHERE ProductID = @ProductID
重建示例
1. 配置数据库。对于必要的步骤,请参见数据访问快速入门中的“快速入门配置”。
2. 通过添加下列代码创建数据库。工厂创建了一个拥有默认配置的 Database 对象。
C#
Database db = DatabaseFactory.CreateDatabase();
Visual Basic
Dim db As Database = DatabaseFactory.CreateDatabase()
3. 通过添加下列代码创建命令。它创建了一个与存储过程一起使用的 DbCommand 。在这里,它是 GetProductName 。它有一个输入参数:ProductID,并返回产品的名称做为结果。
C#
string sqlCommand = "GetProductName";
DbCommand dbCommand = db.GetStoredProcCommand(sqlCommand, productID);
Visual Basic
Dim sqlCommand As String = "GetProductName"
Dim dbCommand As DbCommand = db.GetStoredProcCommand(sqlCommand, productID)
4. 调用 ExecuteScalar,并传递 DbCommand,指明 GetProductName 存储过程将获取产品的名称。
C#
string productName = (string)db.ExecuteScalar(dbCommand);
Visual Basic
Dim productName As String = db.ExecuteScalar(dbCommand)
使用提示
在使用一个命令访问单个条目时考虑下面几点:
- 获取单个条目的另一种方法是使用存储过程输出参数或者返回值和 ExecuteNonQuery 方法一起使用。这种方法在各种条件下都工作得很好。在这种情况下,代码与展示在执行一个命令并访问输出参数的场景中的代码类似。关于选择适当的方法用于查找单个条目的更多信息,请参见 .NET Data Access Architecture Guide。
- 在通过一个结果集的方式使用 ExecuteScalar 方法返回 SQL Server @@Identity 变量时,要注意 SQL Server 返回的 @@Identity 值是 decimal 数据类型,而不是整数类型。如果需要以整数类型获取此值,就必须在客户代码中将返回的对象转换为整数,或者在从存储过程返回 @@Identity 的值时转换它。可以使用 Transact-SQL CAST 函数返回整数值,示例如下:
SELECT CAST(@@Identity AS INTEGER)
8.1.6 - 漫游:在一个事务中完成多个更新
本漫游示范了如何在一个事务中执行多个更新。它假定下列存储过程已创建在代码涉及的连接字符串所对应的数据库中。CREATE PROCEDURE credit
@AccountNo CHAR(20),
@Amount SMALLMONEY
AS
INSERT Credits
VALUES
(@AccountNo, @Amount)
GO
CREATE PROCEDURE debit
@AccountNo CHAR(20),
@Amount SMALLMONEY
AS
INSERT Debits
VALUES
(@AccountNo, @Amount)
GO
重建示例
1. 配置数据库。对于必要的步骤,请参见数据访问快速入门中的“快速入门的配置”。
2. 通过添加下列代码创建数据库。工厂创建了一个拥有默认配置的 Database 对象。
C#
Database db = DatabaseFactory.CreateDatabase();
Visual Basic
Dim db As Database = DatabaseFactory.CreateDatabase()
3. 通过添加下列代码创建命令。它创建了与存储过程一起使用的 DbCommand 。在此,它们是 CreditAccount 和 DebitAccount 。每个存储过程都有一个输入参数:AccountID 和 Amount。
C#
DbCommand creditCommand = db.GetStoredProcCommand("CreditAccount");
db.AddInParameter(creditCommand, "AccountID", DbType.Int32, sourceAccount);
db.AddInParameter(creditCommand, "Amount", DbType.Int32, transactionAmount);
DbCommand debitCommand = db.GetStoredProcCommand("DebitAccount");
db.AddInParameter(debitCommand, "AccountID", DbType.Int32, destinationAccount);
db.AddInParameter(debitCommand, "Amount", DbType.Int32, transactionAmount);
Visual Basic
Dim creditCommand As DbCommand = db.GetStoredProcCommand(sqlCommand)
db.AddInParameter(creditCommand, "AccountID", DbType.Int32, sourceAccount)
db.AddInParameter(creditCommand, "Amount", DbType.Int32, transactionAmount)
sqlCommand = "DebitAccount"
Dim debitCommand As DbCommand = db.GetStoredProcCommand(sqlCommand)
db.AddInParameter(debitCommand, "AccountID", DbType.Int32, destinationAccount)
db.AddInParameter(debitCommand, "Amount", DbType.Int32, transactionAmount)
4. 下列代码展示了如何启动一个事务,然后决定是否提交它,或者如果发生错误时,执行回滚。
C#
using (DbConnection connection = db.CreateConnection())
{
connection.Open();
DbTransaction transaction = connection.BeginTransaction();
try
{
// Credit the first account.
db.ExecuteNonQuery(creditCommand, transaction);
// Debit the second account.
db.ExecuteNonQuery(debitCommand, transaction);
// Commit the transaction.
transaction.Commit();
result = true;
}
catch
{
// Roll back the transaction.
transaction.Rollback();
}
connection.Close();
return result;
}
Visual Basic
Using connection As DbConnection = db.CreateConnection()
connection.Open()
Dim transaction As DbTransaction = connection.BeginTransaction()
Try
' Credit the first account.
db.ExecuteNonQuery(creditCommand, transaction)
' Debit the second account.
db.ExecuteNonQuery(debitCommand, transaction)
' Commit the transaction.
transaction.Commit()
result = True
Catch
' Roll back the transaction.
transaction.Rollback()
End Try
connection.Close()
Return result
End Using
8.1.7 - 漫游:使用 DataSet 更新数据库
本漫游示范了如何使用 DataSet 更新数据库。它假定下列存储过程已创建在代码中所涉及的连接字符串所对应的数据库中。CREATE PROCEDURE AddProduct
(
@ProductName nvarchar(50),
@CategoryID int,
@UnitPrice money
)
AS
INSERT INTO Products (ProductName, CategoryID, UnitPrice)
VALUES (@ProductName, @CategoryID, @UnitPrice)
SELECT ProductID, ProductName, CategoryID, UnitPrice
FROM Products
WHERE ProductID = SCOPE_IDENTITY()
GO
CREATE PROCEDURE DeleteProduct
(
@ProductID int
)
AS
DELETE Products
WHERE ProductID = @ProductID
GO
CREATE PROCEDURE UpdateProduct
(
@ProductID int,
@ProductName nvarchar(50),
@LastUpdate datetime
)
AS
UPDATE Products
SET ProductName = @ProductName
WHERE ProductID = @ProductID AND LastUpdate = @LastUpdate
IF @@ROWCOUNT > 0
-- This statement is used to update the DataSet if changes are done on the updated record (identities, timestamps or triggers )
SELECT ProductID, ProductName, CategoryID, UnitPrice
FROM Products
WHERE ProductID = @ProductID
GO
重建示例
1. 配置数据库。对于必要的步骤,请参见数据访问快速入门中的“快速入门的配置”。
2. 通过添加下列代码创建数据库。工厂通过使用默认配置创建 Database 对象。
C#
Database db = DatabaseFactory.CreateDatabase();
Visual Basic
Dim db As Database = DatabaseFactory.CreateDatabase()
3. 通过添加下列代码获取初始 DataSet。
C#
DataSet productsDataSet = new DataSet();
string sqlCommand = "Select ProductID, ProductName, CategoryID, UnitPrice, LastUpdate " +
"From Products";
DbCommand dbCommand = db.GetSqlStringCommand(sqlCommand);
string productsTable = "Products";
// Retrieve the initial data.
db.LoadDataSet(dbCommand, productsDataSet, productsTable);
Visual Basic
Dim productsDataSet As DataSet = New DataSet
Dim sqlCommand As String = "Select ProductID, ProductName, CategoryID, UnitPrice, LastUpdate " & _
"From Products"
Dim dbCommand As DbCommand = db.GetSqlStringCommand(sqlCommand)
Dim productsTable As String = "Products"
' Retrieve the initial data.
db.LoadDataSet(dbCommand, productsDataSet, productsTable)
4. 通过添加下列代码修改 DataSet。
C#
// Get the table that will be modified.
DataTable table = productsDataSet.Tables[productsTable];
// Add a new product to existing DataSet.
DataRow addedRow = table.Rows.Add(new object[] {DBNull.Value, "New product", 11, 25});
// Modify an existing product.
table.Rows[0]["ProductName"] = "Modified product";
Visual Basic
' Get the table that will be modified.
Dim table As DataTable = productsDataSet.Tables(productsTable)
' Add a new product to existing DataSet.
Dim addedRow As DataRow = table.Rows.Add(New Object() {DBNull.Value, "New product", 11, 25})
' Modify an existing product.
table.Rows(0)("ProductName") = "Modified product"
5. 下列代码展示了如何创建插入新的产品的 DbCommand 对象、删除一个产品,并更新在 DataSet 中的数据。
C#
DbCommand insertCommand = db.GetStoredProcCommand("AddProduct");
db.AddInParameter(insertCommand, "ProductName", DbType.String, "ProductName", DataRowVersion.Current);
db.AddInParameter(insertCommand, "CategoryID", DbType.Int32, "CategoryID", DataRowVersion.Current);
db.AddInParameter(insertCommand, "UnitPrice", DbType.Currency, "UnitPrice", DataRowVersion.Current);
DbCommand deleteCommand = db.GetStoredProcCommand("DeleteProduct");
db.AddInParameter(deleteCommand, "ProductID", DbType.Int32, "ProductID", DataRowVersion.Current);
DbCommand updateCommand = db.GetStoredProcCommand("UpdateProduct");
db.AddInParameter(updateCommand, "ProductID", DbType.Int32, "ProductID", DataRowVersion.Current);
db.AddInParameter(updateCommand, "ProductName", DbType.String, "ProductName", DataRowVersion.Current);
db.AddInParameter(updateCommand, "LastUpdate", DbType.DateTime, "LastUpdate", DataRowVersion.Current);
Visual Basic
Dim insertCommand As DbCommand = db.GetStoredProcCommand("AddProduct")
db.AddInParameter(insertCommand, "ProductName", DbType.String, "ProductName", DataRowVersion.Current)
db.AddInParameter(insertCommand, "CategoryID", DbType.Int32, "CategoryID", DataRowVersion.Current)
db.AddInParameter(insertCommand, "UnitPrice", DbType.Currency, "UnitPrice", DataRowVersion.Current)
Dim deleteCommand As DbCommand = db.GetStoredProcCommand("DeleteProduct")
db.AddInParameter(deleteCommand, "ProductID", DbType.Int32, "ProductID", DataRowVersion.Current)
Dim updateCommand As DbCommand = db.GetStoredProcCommand("UpdateProduct")
db.AddInParameter(updateCommand, "ProductID", DbType.Int32, "ProductID", DataRowVersion.Current)
db.AddInParameter(updateCommand, "ProductName", DbType.String, "ProductName", DataRowVersion.Current)
db.AddInParameter(updateCommand, "LastUpdate", DbType.DateTime, "LastUpdate", DataRowVersion.Current)
6. 通过添加下列代码提交 DataSet ,它展示了如何使用缓存在 DataSet 中的本地数据更新数据库。
C#
int rowsAffected = db.UpdateDataSet(productsDataSet, "Products", insertCommand, updateCommand,
deleteCommand, Microsoft.Practices.EnterpriseLibrary.DataAccess.UpdateBehavior.Standard);
Visual Basic
Dim rowsAffected As Integer = db.UpdateDataSet(productsDataSet, "Products", insertCommand, updateCommand, _
deleteCommand, Microsoft.Practices.EnterpriseLibrary.DataAccess.UpdateBehavior.Standard)