以对象形式从数据库获取数据

  现代的很多编程技术都集中在“数据就是对象”这个概念。如果你在应用层之间使用Data Transfer Objects (DTOs)传输数据的话,这个方法就很有用,使用ORM实现一个数据访问层,或者是客户端查询技术,例如LINQ。

  数据库访问模块实现了这个功能,允许你执行SQL或者是存储过程,可以返回一个对象序列,但是要求序列实现IEnumerable接口。

  关于Accessors

  模块提供了两个方法来实现这种查询要求,SprocAccessor和SqlStringAccessor。你可以使用Database类的ExecuteSprocAccessor和ExecuteSqlStringAccessor,或者是创建一个Accessor,然后调用它的Execute方法。

  下面是一张查询示意图

  微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_sql

  Accessor使用另外两个对象,一个用来管理传入accessor的参数,一个用来将数据库返回的数据行映射成客户端需要的对象。

  如果你没有指定一个参数映射,accessor会使用默认的参数映射。默认情况下这个功能只能用于执行SQL Server和Oracle的存储过程。不能执行SQL 语句,或者是其他的数据库和provider,如果需要的话,可以自定义参数映射器。

  如果你没有指定一个对象映射,模块使用默认的对象映射,根据列的名称映射到对象的属性。你也可以自定义对象映射,将列映射到指定的对象属性上去。

  创建和执行Accessor

  

 


微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_02微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_03代码


// Create an object array and populate it with the required parameter values

object[] params = new object[] { "%bike%" };

// Create and execute a sproc accessor that uses the default

// parameter and output mappings.

var productData = defaultDB.ExecuteSprocAccessor<Product>("GetProductList",

params);

// Perform a client‐side query on the returned data. Be aware that

// the orderby and filtering is happening on the client, not in the database.

var results = from productItem in productData

where productItem.Description != null

orderby productItem.Name

select new { productItem.Name, productItem.Description };

// Display the results

foreach (var item in results)

{

A Guide to Developing with Enterprise Library 5.0 41

Console.WriteLine("Product Name: {0}", item.Name);

Console.WriteLine("Description: {0}", item.Description);

Console.WriteLine();

}


 

 

  上面假设由一个Product类,有ID,Name,Description三个属性。

  创建和使用映射Mappers

  在某些情况下,你需要自定义参数映射,将你的参数传递给要执行查询的accessor。这种典型的情况发生在,你需要执行一个SQL语句,和一个不支持参数的数据库进行交互,或者是默认的参数映射的参数个数或者是类型不匹配。参数映射类需要实现IParameterMapper接口,有一个AssignParameters方法引用了Command对象作为参数,你需要做的就是将需要的参数加入Command对象的Parameters集合。

  在更多的情况你需要一个自定义对象映射。为了帮助你完成这个需求,模块提供了MapBuilder类,用它可以创建列和对象属性的映射关系。

  默认情况,accessor可以返回一个简单的对象序列。但是,有时候需要返回一个复杂的对象序列,例如,返回Orders的同时返回相关的OrderLines。简单的映射不能满足这样的需求,MapBuilder类也不能满足了。你需要实现IResultSetMapper接口,自定义对象映射关系。

  获取XML数据

  企业库提供了ExecuteXmlReader方法返回一个XmlReader对象。目前为止,还只能支持SQL Server数据库,意味着你只能用SqlDatabase类。

  你需要把Database转换成SqlDatabse,或者是用构造函数直接创建一个SqlDatabse。

  

 


微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_02微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_03代码


static SqlDatabase sqlServerDB = null;

// Resolve a SqlDatabase object from the container using the default database.

sqlServerDB

= EnterpriseLibraryContainer.Current.GetInstance<Database>() as SqlDatabase;

// Specify a SQL query that returns XML data

string xmlQuery = "SELECT * FROM OrderList WHERE State = @state FOR XML AUTO";

// Create a suitable command type and add the required parameter

// NB: ExecuteXmlReader is only available for SQL Server databases

using (DbCommand xmlCmd = sqlServerDB.GetSqlStringCommand(xmlQuery))

{

xmlCmd.Parameters.Add(new SqlParameter("state", "Colorado"));

using (XmlReader reader = sqlServerDB.ExecuteXmlReader(xmlCmd))

{

while (!reader.EOF) // Iterate through the elements in the XmlReader

{

if (reader.IsStartElement())

{

Console.WriteLine(reader.ReadOuterXml());

}

}

}

}


 

 

  获取单个值

  

 


微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_02微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_03代码


// Create a suitable command type for a SQL statement

// NB: For efficiency, aim to return only a single value or a single row.

using (DbCommand sqlCmd

= defaultDB.GetSqlStringCommand("SELECT [Name] FROM States"))

{

// Call the ExecuteScalar method of the command

Console.WriteLine("Result using a SQL statement: {0}",

defaultDB.ExecuteScalar(sqlCmd).ToString());

}

// Create a suitable command type for a stored procedure

// NB: For efficiency, aim to return only a single value or a single row.

using (DbCommand sprocCmd = defaultDB.GetStoredProcCommand("GetStatesList"))

{

// Call the ExecuteScalar method of the command

Console.WriteLine("Result using a stored procedure: {0}",

defaultDB.ExecuteScalar(sprocCmd).ToString());

}


 

  异步获取数据

  1)准备配置文件

  需要在连接字符串中添加Asynchronous Processing=true或者是async=true。

  

 


微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_02微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_03代码


<connectionStrings>

<add name="AsyncExampleDatabase"

connectionString="Asynchronous Processing=true; Data Source=.\SQLEXPRESS;

Initial Catalog="MyDatabase"; Integrated Security=True;"

providerName="System.Data.SqlClient" />

...

</connectionStrings>


 

  另外,企业库中的异步访问数据库只支持SQL Server。在Database类由一个属性SupportsAsync,可以用来查询当前数据库是否支持异步访问。

  

 

 

 


微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_02微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_03代码


private static bool SupportsAsync(Database db)

{

if (db.SupportsAsync)

{

Console.WriteLine("Database supports asynchronous operations");

return true;

}

Console.WriteLine("Database does not support asynchronous operations");

return false;

}


 

  使用异步访问数据库通常需要一个callback,在调用端会打开另外一个线程。这个callback通常不会直接访问winform和wpf的用户界面。你需要在用户界面添加事件,然后通过委托的方式更新用户界面。

  委托可以使用Lambda表达式实现。

 


微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_02微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_03代码


DbCommand cmd = asyncDB.GetStoredProcCommand("ListOrdersSlowly");

asyncDB.AddInParameter(cmd, "state", DbType.String, "Colorado");

asyncDB.AddInParameter(cmd, "status", DbType.String, "DRAFT");

// Execute the query asynchronously specifying the command and the

// expression to execute when the data access process completes.

asyncDB.BeginExecuteReader(cmd,

asyncResult =>

{

// Lambda expression executed when the data access completes.

try

{

using (IDataReader reader = asyncDB.EndExecuteReader(asyncResult))

{

A Guide to Developing with Enterprise Library 5.0 47

Console.WriteLine();

DisplayRowValues(reader);

}

}

catch (Exception ex)

{

Console.WriteLine("Error after data access completed: {0}", ex.Message);

}

}, null);

  

 

  异步获取对象形式返回的数据

  

 


微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_02微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_03代码


object[] paramArray = new object[] { "%bike%", 20 };

// Create the accessor. This example uses the simplest overload.

var accessor = asyncDB.CreateSprocAccessor<Product>("GetProductsSlowly");

// Execute the accessor asynchronously specifying the callback expression,

// the existing accessor as the AsyncState, and the parameter values array.

accessor.BeginExecute(

asyncResult =>

{ // Lambda expression executed when the data access completes.

try

{

// Accessor is available via the asyncResult parameter

var acc = (IDataAccessor<Product>) asyncResult.AsyncState;

// Obtain the results from the accessor.

var productData = acc.EndExecute(asyncResult);

// Perform a client‐side query on the returned data.

// Be aware that the orderby and filtering is happening

// on the client, not inside the database.

var results = from productItem in productData

where productItem.Description != null

orderby productItem.Name

select new { productItem.Name, productItem.Description };

// Display the results

Console.WriteLine();

foreach (var item in results)

{

Console.WriteLine("Product Name: {0}", item.Name);

Console.WriteLine("Description: {0}", item.Description);

Console.WriteLine();

}

}

catch (Exception ex)

{

Console.WriteLine("Error after data access completed: {0}", ex.Message);

}

}, accessor, paramArray);


 

  更新数据库

  

 


微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_02微软企业库5.0学习笔记(三十四)数据访问模块 各种获取数据的方式_DataAccess_03代码


string oldDescription

= "Carries 4 bikes securely; steel construction, fits 2\" receiver hitch.";

string newDescription = "Bikes tend to fall off after a few miles.";

// Create command to execute the stored procedure and add the parameters.

DbCommand cmd = defaultDB.GetStoredProcCommand("UpdateProductsTable");

defaultDB.AddInParameter(cmd, "productID", DbType.Int32, 84);

defaultDB.AddInParameter(cmd, "description", DbType.String, newDescription);

// Execute the query and check if one row was updated.

if (defaultDB.ExecuteNonQuery(cmd) == 1)

{

// Update succeeded.

}


else

{

Console.WriteLine("ERROR: Could not update just one row.");

}

// Change the value of the second parameter

defaultDB.SetParameterValue(cmd, "description", oldDescription);

// Execute query and check if one row was updated

if (defaultDB.ExecuteNonQuery(cmd) == 1)

{

// Update succeeded.

}

else

{

Console.WriteLine("ERROR: Could not update just one row.");

}


 

未完待续。。。。。。。。。。。。。。。。。。。。。