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


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

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

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

      关于Accessors

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

      下面是一张查询示意图

      

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

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

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

      创建和执行Accessor

      

    // 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。

      

    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());
    }
    }
    }
    }

      获取单个值

      

    // 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。

      

    <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,可以用来查询当前数据库是否支持异步访问。

      

    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表达式实现。

    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);

      

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

      

    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);

      更新数据库

      

    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.");
    }
  • 相关阅读:
    Nim or not Nim? HDU
    邂逅明下 HDU
    4.1.8 巴什博弈
    4.1.7 Cutting Game(POJ 2311)
    0.1.2 max_element和min_element的用法
    bzoj 2152 聪聪可可 树形dp
    hdu 5976 Detachment 脑洞题 猜结论
    hdu 5974 A Simple Math Problem gcd(x,y)=gcd((x+y),lcm(x,y))
    hdu 5971 Wrestling Match 二分图染色
    Codeforces 842C Ilya And The Tree 树上gcd
  • 原文地址:https://www.cnblogs.com/DoNetCShap/p/2295530.html
Copyright © 2020-2023  润新知