加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

数据适配器的相关知识收集

(2009-03-27 09:35:02)
标签:

杂谈

分类: 技术

数据适配器是 ADO.NET 托管提供程序(用于在数据源和数据集之间通信的一组对象)的组成部分。(除适配器以外,托管提供程序还包括连接对象、数据读取器对象和命令对象。)适配器用于在数据源和数据集之间交换数据。在许多应用程序中,这意味着从数据库将数据读入数据集,然后从数据集将已更改数据写回数据库。然而,数据适配器可以在任意源和数据集之间移动数据。例如,可能会有在 Microsoft Exchange 服务器和数据集之间移动数据的适配器。
DATABASE LINK 两台不同的数据库服务器,从一台数据库服务器的一个用户读取另一台数据库服务器下的某个用户的数据,这个时候可以使用dblink。
其实dblink和数据库中的view差不多,建dblink的时候需要知道待读取数据库的ip地址,ssid以及数据库用户名和密码。

C#:通过数据适配器进行更新

除了SqlDataAdapter最有可能包含的 SelectCommand之外,还可以定义InsertCommand、 UpdateCommand 和 DeleteCommand。顾名思义,这些对象都是适用于相应提供程序的命令对象(例如SqlCommand 或 OleDbCommand)实例。

    有了这种灵活性后,就可以自由调整应用程序,对频繁使用的命令(例如select和insert)采用合适的存储过程来执行,对不常使用的命令(例如delete)采用SQL命令的方式执行。一般应为所有的数据库交互操作提供存储过程,因为这会更快,更容易调整。

    本节的示例重新使用“调用存储过程”一节中的存储过程,插入、更新和删除Region记录,再把这些与上面编写的RegionSelect过程结合起来,生成一个新示例,这个示例使用这些命令来检索和更新DataSet中的代码。代码的主体如下所示。

    1. 插入一个新行

    把新行添加到DataTable中有两种方式。第一种方式是调用NewRow()函数,返回一个空行,然后向其填充数据,最后把它添加到Rows集合中:
    DataRow r = ds.Tables["Region"].NewRow();
    r["RegionID"]=999;
    r["RegionDescription"]="North West";
    ds.Tables["Region"].Rows.Add(r);

    第二种方式是把一组数据传送给Rows.Add()方法:
    DataRow r = ds.Tables["Region"].Rows.Add
                 (new object [] { 999 , "North West" });

    DataTable中的每个新行都把自己的RowState设置为Added,在对数据库进行修改前,这个示例先把记录清空,然后把下面的行添加到DataTable中(以任何一种方式)。注意右边一列显示行的状态:
    New row pending inserting into database
       Eastern                                            Unchanged
       Western                                           Unchanged
       Northern                                           Unchanged
       Southern                                          Unchanged
      999 North West                                     Added

    要在DataAdapter中更新数据库,调用Update方法:
    da.Update(ds , "Region");

    对于DataTable中的每一新行,这将执行存储过程(在本例中是RegionInsert),然后再次把DataTable中的记录清空,查看对数据库进行的修改。
    New row updated and new RegionID assigned by database
       Eastern                                            Unchanged
       Western                                           Unchanged
       Northern                                           Unchanged
       Southern                                          Unchanged
       North West                                       Unchanged

    看看DataTable中的最后一行。把代码中的RegionID设置为999,但在执行RegionInsert存储过程后,该值改为5,这是本例的目的—— 数据库会生成主键码,并且更新DataTable中的数据。DataTable中的数据更新是因为源代码中的SqlCommand定义会把UpdatedRowSource属性设置为UpdateRowSource.OutputParameters:
    SqlCommand aCommand = new SqlCommand("RegionInsert" , conn);      
    aCommand.CommandType = CommandType.StoredProcedure;
    aCommand.Parameters.Add(new SqlParameter("@RegionDescription" ,
                                SqlDbType.NChar ,
                                50 ,
                                "RegionDescription"));
    aCommand.Parameters.Add(new SqlParameter("@RegionID" ,
                                SqlDbType.Int,
                                0 ,
                                ParameterDirection.Output ,
                                false ,

                                0 ,
                                0 ,
                                "RegionID" ,   // Defines the SOURCE column
                                DataRowVersion.Default ,
                                null));
    aCommand.UpdatedRowSource = UpdateRowSource.OutputParameters;

    无论何时DataAdapter执行这个命令,输出参数都应映射回数据行的源,在本例中是DataTable中的一行,该标志说明了应更新什么数据—— 存储过程有一个输出参数映射回DataRow,它应用的列是RegionID,这是在命令定义中定义的。

    UpdateRowSource的值如表21-9所示。

 UpdateRowSource值  说   
 Both
  存储过程可以返回输出参数和一个完整的数据库记录。这些数据源都用于更新源数据行
 FirstReturnedRecord
  该命令返回一个记录,该记录的内容应合并到最初的源DataRow中,当给定的表有许多默认(或计算)列时,使用这个值很有用,因为在执行插入语句之后,这些行需要与客户机上的DataRow同步。例如INSERT (列) INTO (表) WITH (主键码),SELECT (列) FROM (表) WHERE (主键码)。返回的记录应合并到源数据行上
 None  删除从该命令返回的所有数据
 OutputParameters  命令的任何输出参数都映射到DataRow的对应列上
 


表  21-9

    2. 更新现有的行

    更新DataTable中一个已经存在的行只需使用带有一个列名或列号的DataRow索引器即可,如下面的代码所示:
    r["RegionDescription"]="North West England";
    r[1] = "North East England";
    这两个语句是等价的(在本例中):
    Changed RegionID 5 description
       Eastern                                    Unchanged
       Western                                   Unchanged
       Northern                                   Unchanged
       Southern                                  Unchanged
       North West England                  Modified

    在更新数据库前,被更新的行应把其状态设置为Modified,其值如上所示。

    3. 删除一行

    删除一行需要调用Delete()方法:r.Delete();

    被删除的行把其行状态设置为Deleted,但不能从被删除的DataRow中读取列,因为它们已经不再有效,当调用适配器的Update()方法时,所有被删除的行都会使用DeleteCommand,在本例中是执行RegionDelete存储过程。

C#:用数据适配器来填充DataSet

前面讨论数据行的一节简要介绍了SqlDataAdapter类,使用该类的代码如下所示:
    string select = "SELECT ContactName,CompanyName FROM Customers";
    SqlConnection conn = new SqlConnection(source);
    SqlDataAdapter da = new SqlDataAdapter(select , conn);
    DataSet ds = new DataSet();
    da.Fill(ds , "Customers");

    突出显示的两行代码显示了SqlDataAdapter类—— 其他数据适配器在功能上实际上与SqlDataAdapter是完全相同的。

    数据适配器类都派生于同一个基类,而不是一组接口,其他数据库类也是这样。继承结构如下所示:
    System.Data.Common.DataAdapter
    System.Data.Common.DbDataAdapter
    System.Data.Odbc.OdbcDataAdapter
    System.Data.OleDb.OleDbDataAdapter
    System.Data.OracleClient.OracleDataAdapter
    System.Data.SqlClient.SqlDataAdapter

    为了把数据插入到DataSet中,需要执行某种形式的命令以选择该数据。该命令可以是SQL SELECT语句,一个存储过程的调用,或者是TableDirect命令(用于OleDb提供程序)。上面的示例使用了SqlDataAdapter的一个构造函数,把传送过来的SQL SELECT子句转换为一个SqlCommand,在适配器上调用Fill方法时执行这个命令。

    在本章前面的存储过程示例中,定义了INSERT、UPDATE和DELETE命令,但没有给出一个SELECT过程,本节介绍该过程,并说明如何从SqlDataAdapter上调用存储过程,把数据填充到DataSet中。
在数据适配器上使用存储过程

    首先需要定义一个存储过程, SELECT存储过程如下所示:
    CREATE PROCEDURE RegionSelect AS
      SET NOCOUNT OFF
      SELECT * FROM Region
    GO

    这个存储过程可以直接输入到SQL Server查询分析器中,或者可以运行这个示例所使用的StoredProc.sql文件。

    接着,需要定义一个执行该存储过程的SqlCommand,这段代码非常简单,并且大部分已经在前面“执行命令”的一节中介绍过了:
    private static SqlCommand GenerateSelectCommand(SqlConnection conn )
    {
       SqlCommand  aCommand = new SqlCommand("RegionSelect" , conn);
       aCommand.CommandType = CommandType.StoredProcedure;
       aCommand.UpdatedRowSource = UpdateRowSource.None;
       return aCommand;
    }

    这个方法生成了一个SqlCommand,该SqlCommand在执行时会调用RegionSelect过程。最后是把这个命令和SqlDataAdapter类关联起来,调用Fill方法:
    DataSet ds = new DataSet();
    // Create a data adapter to fill the DataSet
    SqlDataAdapter da = new SqlDataAdapter();
    // Set the data adapter's select command
    da.SelectCommand = GenerateSelectCommand (conn);
    da.Fill(ds , "Region");

    其中创建了一个新SqlDataAdapter,把生成的SqlCommand赋给数据适配器的SelectCommand属性,然后调用执行存储过程的Fill方法,把返回的所有行插入到Region数据表中(在本例中,它是由运行库生成的)。

    数据适配器不仅仅能通过执行命令来选择数据,“保存对数据集的修改”一节会介绍数据适配器的其他功能。

DataSet

DataSetADO.NET的中心概念.可以把DataSet当成内存中的数据库,DataSet是不依赖与数据库的独立数据集合.所谓独立,就是说,即使断开数据链路,或者关闭数据库,DataSet依然是可用的.DataSet在内部是用XML来描述数据的,由于XML是一种与平台无关、与语言无关的数据描述语言,而且可以描述复杂关系的数据,比如父子关系的数据,所以DataSet实际上可以容纳具有复杂关系的数据,而且不在依赖于数据库链路。

  正是由于DataSet才使得程序员在编程时可以屏蔽数据库之间的差异,从而获得一致的编程模型。DataSet支持多表、表间关系、数据约束等,和关系数据库的模型基本一致。

  DataSet 是 ADO.NET 结构的主要组件,它是从数据源中检索到的数据在内存中的缓存。DataSet 由一组 DataTable 对象组成,您可使这些对象与 DataRelation 对象互相关联。您还可通过使用 UniqueConstraint 和 ForeignKeyConstraint 对象在 DataSet 中实施数据完整性。有关使用 DataSet 对象的详细信息,请参见 在 ADO.NET 中使用 DataSet。

  尽管 DataTable 对象中包含数据,但是 DataRelationCollection 允许您遍览表的层次结构。这些表包含在通过 Tables 属性访问的 DataTableCollection 中。当访问 DataTable 对象时,请注意它们是按条件区分大小写的。例如,如果一个 DataTable 被命名为“mydatatable”,另一个被命名为“Mydatatable”,则用于搜索其中一个表的字符串被认为是区分大小写的。但是,如果“mydatatable”存在而“Mydatatable”不存在,则认为该搜索字符串不区分大小写。有关使用 DataTable 对象的更多信息,请参见 创建 DataTable。

  DataSet 可将数据和架构作为 XML 文档进行读写。数据和架构可通过 HTTP 传输,并在支持 XML 的任何平台上被任何应用程序使用。可使用 WriteXmlSchema 方法将架构保存为 XML 架构,并且可以使用 WriteXml 方法保存架构和数据。若要读取既包含架构也包含数据的 XML 文档,请使用 ReadXml 方法。

  在典型的多层实现中,用于创建和刷新 DataSet 并依次更新原始数据的步骤包括:

  通过 DataAdapter 使用数据源中的数据生成和填充 DataSet 中的每个 DataTable。

  通过添加、更新或删除 DataRow 对象更改单个 DataTable 对象中的数据。

  调用 GetChanges 方法以创建只反映对数据进行的更改的第二个 DataSet。

  调用 DataAdapter 的 Update 方法,并将第二个 DataSet 作为参数传递。

  调用 Merge 方法将第二个 DataSet 中的更改合并到第一个中。

  针对 DataSet 调用 AcceptChanges。或者,调用 RejectChanges 以取消更改。

  需要注意是是:dataset所有数据都加载在内存上执行的,可以提高数据访问速度,提高硬盘数据的安全性。极大的改善了程序运行的速度和稳定性。

用数据适配器更新添加数据

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;
namespace RescItem
{
    class Program
    {
        static void Main(string[] args)
        {
            using (SqlConnection Conn = new SqlConnection(DB.ConnStr))
            {
                SqlDataAdapter dataAdapter = new SqlDataAdapter("select * from First",Conn);
                dataAdapter.UpdateCommand = new SqlCommand("update First set publisher=@publisher,title=@title where ID=@ID",Connn);
                dataAdapter.UpdateCommand.Parameters.Add("@publisher",SqlDbType.VarChar,50,"publisher");
                dataAdapter.UpdateCommand.Parameters.Add("@title",SqlDbType.VarChar,250,"title");
                SqlParameter paramter = dataAdapter.UpdateCommand.Parameters.Add("@ID",SqlDbType.Int);
                paramter.SourceColumn = "ID";
                paramter.SourceVersion=DataRowVersion.Original;

                dataAdapter.InsertCommand = new SqlCommand("insert into First(Publisher,Title,Information,PubDate)values(@Publisher,@Title,@Information,@PubDate)",Conn);
                dataAdapter.InsertCommand.Parameters.Add("@Publisher",SqlDbType.VarChar,50,"publisher");
                dataAdapter.InsertCommand.Parameters.Add("@Title", SqlDbType.VarChar, 250, "title");
                dataAdapter.InsertCommand.Parameters.Add("@Information",SqlDbType.Text,1000,"information");
                dataAdapter.InsertCommand.Parameters.Add("@Pubdate",SqlDbType.DateTime,100,"pubdate");

                DataTable First = new DataTable();
                dataAdapter.Fill(First);
                DataRow FirstRow = First.Rows[0];
                FirstRow["publisher"] = "河南";
                FirstRow["title"] = "河南您好";

                DataRow More = First.NewRow();
                More["publisher"] = "中国您好";
                More["Title"] = "中国您好";
                More["Information"] = "河南您好";
                More["Pubdate"] = "2009-9-9";
                First.Rows.Add(More);

                dataAdapter.Update(First);

            }
        }
    }
}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有