使用ADO.NET轻松操纵数据库(二)

类别:数据库 点击:0 评论:0 推荐:

     首先,ADO.NET中使用了DataAdapter 来处理与数据库的联机与脱机。当时开发人员设计了DataAdapter是为了能够处理脱机数据,方便操作,关于这一点,只要调用其Fill()方法即可,这时会在DataSet中创建一个新的名为“Table“的DataTable.要重新指定名可用DataAdapter.Fill(DataSet,“Tabelname“)。此时connection也关闭了。DataAdapter既可以用来提交查询,并将结果存储到DataSet中,也可以用来向数据库传递更改。仅仅使用其Update方法即可达到向数据库提交存储地DatSet中的更改。

    DataAdapter将查询的结果存储在DataSet或DataTable对象中,当执行这一过程的时候,DataAdapter使用了一个Command来与数据库通讯,并在内部使用了DataReader来获取查询结果,最后才将结果复制到DataSet新行中去。这也是Fill的过程。如果有两个DataAdapter对象,都使用相同的Connection对象,在创建的时候就会创建两个Connection对象,而不是同一个,这种情况的解决方案是:


   SqlConnection con=new SqlConnection("server=localhost;database=Northwind;Trusted_Connection=Yes;")
   SqlDataAdapter da=new SqlDataAdapter("select CategoryID,Description from Categories",con);
   SqlDataAdapter da=new SqlDataAdapter("select CategoryID,Description from Customers",con);

而不是将查询字符串,单独写成一行。

   有时候可能并不希望DataSet中的架构与数据库中的架构相同,这种情况的解决方案之一是可以采用别名的方法,即select id as Product ID,amount as Product Amount from product;另外一种解决方案就是使用DataAdapter提供的TableMappings集合机制,通过它就可以将查询结果映射到DataSet结构中,这种方法更方便,更灵活。TableMappings属性返回一个DataTableMappingsCollection对象,其中包含了一组DataTableMappings,只要DataSet中相应的表名称与数据库中的表名相同,即可以使用它来创建一个映射(DataSet中可以有多个表)。TableMappings里还有一个ColumnMappings属性,其用法与TableMappings相似。其原理是DataAdapter从数据库读取数据后,利用DataReader从结果集中获取列名称,有一点特别要注意,即只能获取列名称而无法获取表名称,DataAdapter事先假定表名称为Table,接着遇到映射语句则进行表映射。不说了,看代码:

  DataColumnMapping colMap;
   SqlConnection con=new SqlConnection("server=localhost;database=Northwind;Trusted_Connection=Yes;");
   SqlDataAdapter da=new SqlDataAdapter("select CategoryID,Description from Categories",con);
   DataSet ds=new DataSet();

   DataTableMapping tblMap=da.TableMappings.Add("Table","Ca"); //这里Table为关键,映射表名为Ca

   colMap=tblMap.ColumnMappings.Add("CategoryID","ID"); //映射列表
   colMap=tblMap.ColumnMappings.Add("Description","描述");
   // Response.Write(tblMap.DataSetTable.ToString());
    da.Fill(ds);
   DataTable dt=ds.Tables["Ca"]; //这里是映射后的表名,如果仍为数据库的表名,则无效,特别注意
   this.DataGrid1.DataSource=dt;
   this.DataGrid1.DataBind();

运行代码后就会发现DataGrid1上的列名为ID和描述 (^_^)

(注:使用DataTableMapping 之前要前导入名空间System.Data.Common;)

还可以使用AddRange方法来简化表和列的映射:(一些代码同上面)

  .......                
   DataTableMapping tblMap=da.TableMappings.Add("Table","Ca");       DataColumnMapping[] colMapArray=new DataColumnMapping[]{new DataColumnMapping("CategoryID","产   品号"),new DataColumnMapping("Description","描述")};        tblMap.ColumnMappings.AddRange(colMapArray);     
   ......                  

这种映射关系只能从数据库中读取展示给用户,如果要将映射后的Table的更改提交给数据库,这时库发现其中列与库中列不同,便会发生异常,DataAdapter 同时也提供了MissingMappingAction属性来处理。

DataAdapter1.MissingMappingAction=MissingMappingAction.Passthrough/Ignore/Error

它接受MissingMappingAction的枚举值,Passthrough这个值表示如果在库中找不到与DataSet中相同列的话,就将此列映射到库中,Ignore枚举值表示忽略示出现的列,Error表示找不到相应的列则抛出异常。

分页:

分页在应用中是常有的事,而DataAdapter本身也提供了分页的简单功能,如:DataAdapter1.Fill(dataset,startrow,rownum,“tablename“)这种功能用于数据量较小的查询就可以,但当有大量数据的时候,就会发现这种分页的问题的存在。它的原理是假如有一百行数据,分成十页,每页十行,当获取每一页的时候,返回前10行,再接着,第二页,删除了前10行而获取接下的10行,在这一次中,只是为了获取10行数据,但数据库却返回了20行,依此类推,第10页的时候就会返回100行,而DataAdapter本身就帮我们删除了90行,因为我们看上去返回的还是10行,这种性能太低。因此本篇继续介绍另外一种性能较高的分页方法。实际上这种分页方法是将上一页最后一行的键值存储下来,直接在SQL语句中就过滤掉了,不象前面那种到DataAdapter这边才过滤掉。例:

con=new SqlConnection("server=localhost;database=Northwind;Trusted_Connection=Yes;");
da=new SqlDataAdapter("select top 50 CustomerID,CompanyName from Customers where CustomerID>'BOTTM'",con); 
ds=new DataSet();
da.Fill(ds,"Categories");
this.DataGrid1.DataSource=ds.Tables["Categories"]; this.DataGrid1.DataBind();
con.Close();

这里假如上一页最后一个键值为”BOTTM”,可以将它用参数替代掉,这样就查出了在'BOTTM'之后的50行。这种方法实现简单效率也高。

本文地址:http://com.8s8s.com/it/it20789.htm