zoukankan      html  css  js  c++  java
  • ADO.NET(二)

    内存中的数据库--DataSet类
    DataSet类是数据的脱机容器。数据集由一组数据表组成,每个表都有一些数据列和数据行
    DataSet对象中包含:数据表数据关系


    实例化DataSet:
      DataSet ds = new DataSet();
       //这只是生成了一个空的数据集,里面不包含任何表。
    DataSet属性:
      Tables:(DataTableCollection)表集合,用来管理其中的各子表。
      Relations:(DataRelationCollection)关系集合,用来管理其中的表与表之间的关系。
    DataSet方法
      WriteXml():将DataSet的内容写入的内容写入XML文件中。
      ReadXml():将xml文件中的内容写到文件中的内容写到DataSet中。

    内存中的表--数据表(车延禄)
    数据表非常类似于物理数据库表,它由列组成,可能包含0行或多行数据。数据表也可以定义主键码(可以是一个列或多个列),列上也可以包含约束。


    实例化DataTable:
      DataTable dt = new DataTable();
       //这里的dt也只是一个空对象,其中没有任何列和行
      ds.Tables.Add(dt);
       //将数据表加入到数据集中
    DataTable属性:
      Rows:(DataRowCollection)管理表中所有的行
      Columns:(DataColumnCollection)管理表中所有的列
      Constraints:(ConstraintCollection)管理表中所有的约束集合
      TableName:(String)数据表在数据集中的标识名
      PrimaryKey:(DataColumn[])表的主键列的数组
      DefaultView:(DataView)表的默认视图
    DataTable方法:
      NewRow():(DataRow)根据表的结构生成一个新行对象。
      
    DataColumn数据列:
    数据表中的列
    实例化:
      DataColumn dc = new DataColumn();
      
      DataColumn dc = new DataColumn(string,Type);
      
      dt.Columns.Add(dc);//将列对象加入到表的列集合中
    DataColumn属性:
      AllowDBNull:(bool)是否允许该列为空
      AutoIncrement:(bool)该列是否是自增长表
      ColumnName:(string)当前列的列名
      DataType:(Type)当前列的数据类型
      MaxLength:(int)当前列的宽度
      ReadOnly:(bool)当前列是否是只读列(只能插入删除,但不能修改)
      Unique:(bool)当前列是否是唯一列
      DefaultValue:(object)当前列的默认值
      (车延禄)
    DataRow数据行:
    表中的数据行,创建表的时候一定要先创建列再添加行
    DataRow 对象一般是用DataTable对象的NewRow方法来生成新行
    方法:
      Delete():删除当前行
    GetChildRows():获取相关联子表中的对应的行(需要事先在Dataset中建立起表的关联)
      GetParentRow():获取相关联父表中对应的行(需要事先在Dataset中建立起表的关联)
    整个数据行有一个状态标志RowStateRowState标志跟踪对DataTable所作的所有改变,当数据与数据库保持一致时,行的状态标志用于确定应执行什么SQL操作。
      Added--把新数据行添加到DataTable的Rows集合中。在客户机中创建的所有行都设置为这个值,最终在与数据库保持一致时,会使用SQL INSERT语句
      Deleted--通过DataRow.Delete()方法把DataTable中的数据行标记为删除。该行仍存在DataTable中,但在屏幕上看不到它(除非显式设置DataView)。DataView在下一章讨论。在DataTable 中标记为已删除的Rows将在与数据库保持一致时从数据库中删除
      Detached--数据行在创建后立即显示为这个状态,调用DataRow.Remove()也可以返回这个状态。分立的行不是任何DataTable的一部分,因此处于这种状态的行不能使用任何SQL语句
      Modified--如果列中的值发生了改变,就会修改一行数据
      Unchanged--自从最后一次调用AcceptChanges以来,数据行都没有发生改变

    手动创建DataSet的示例:
    DataTable dt = new DataTable(“login”); //生成新的数据表
    //定义一个新列“ids” ,类型为整型
    DataColumn dc0 = new DataColumn("ids", Type.GetType("System.Int32"));
    dt.Columns.Add(dc0); //将“ids”加入到表中去
    //向表中加入“username”列,类型为字符串型(车延禄)
    dt.Columns.Add("username",Type.GetType("System.String"));
    dt.Columns.Add(“password”);// 向表中加入“password”列,类型为字符串型
    dt.Columns["password"].DataType = Type.GetType("System.String");
    dt.Columns[0].AutoIncrement AutoIncrement = true;// 设为自增长列
    dt.Columns[1].Unique Unique = true;// 设为唯一列
    dt.Columns[1].ReadOnly ReadOnly = true;// 设为只读列
    dt.Columns[2].DefaultValue DefaultValue = “666666”; //为该列设置默认值
    dt.Columns[2].MaxLength MaxLength = 8;// 指定该列的最大长度

    DataRow dr1 = DataRow dr1 = dt.NewRow();// 生成一个新行
    dr1[1] = "aaa";//向表中加两行数据,ids 为自增长,password 为默认值列
    dt.Rows.Add(dr1);
    DataRow dr2 = dt.NewRow();
    dr2[1] = "bbb";
    dt.Rows.Add(dr2);
    //显示表中的内容
    for(int i=0;i<dt.Rows.Count;i++)
    {
       for(int j=0;j<dt.Columns.Count;j++;j++)
       {
         Console.Write(dt.Rows[i][j].ToString()+"\t");
       }
       Console.Write("\n"); Console.Write("\n");
    }
    DataSet ds = new DataSet();// 定义一个空的DataSet
    ds.Tables.Add(dt);// 将dt表加入到该DataSet 中
      
    DataView数据视图
    表示用于排序、筛选、搜索、编辑和导航的DataTable 的可绑定数据的自定义视图,另外,可自定义DataView来表示DataTable中数据的子集。
    也可以直接对数据视图进行直接的添加、修改、删除和查询,但这不建议使用,可以直接对表进行操作
    实例化DataView对象
      DataView dv = new DataView();
       dv.Table = ds.Tables[0];
      
       DataView dv = ds.Tables[0].DefaultView;
      
    常用属性:
      Count:在设置RowFilter和RowStateFilter之后获取的DataView中的记录数量
      RowFilter:获取或设置用于筛选在DataView中查看哪些行的表达式。类似于SQL中的where子句
      Sort:获取或设置DataView的一个或多个排序列以及排序顺序。类似于SQL中的order by子句
      Table:获取或设置源数据表
      
    Constraint数据表的约束
    Constraint用来在DataTable的一个或多个DataColumn对象上强制的约束,用于维护DataTable中的数据的完整性的规则
    主要包括:
      UniqueConstraint:创建主键约束或唯一键约束
      ForeignKeyConstraint:创建外键约束
       其它完整性约束可以通过DataColumn对象的属性值来进行设置
    UniqueConstraint 类:
       常用构造函数:
       (约束名, 所属的列, 是否设为主键约束)
       主要属性:
       Columns:该约束所影响到的列
       ConstraintName:该约束的名子
       IsPrimaryKey:该约束是否为主键
      创建主键一般有两种方式:
       1.使用DataTable的PrimaryKey属性来设置主键列
         DataColumn[] pk = new DataColumn[1];
         pk[0] = dt.Columns["ProductID"];
         dt.PrimaryKey = pk;

       2.使用UniqueConstraint类来设置主键列
        DataColumn[] pk = new DataColumn[1];
         pk[0] = dt.Columns["ProductID"];
         dt.Constraints.Add(new UniqueConstraint("PK_Products", pk[0]),true);

    ForeignKeyConstraint 类:
       常用构造函数:
       (约束名,父表的主键列,子表的外键列)
       主要属性:
       Columns:该约束所影响的列
       RelatedColumns:相关的主表中的主键列
       Table:所属的表
       RelatedTable:相关的主表
       ConstraintName:该约束的约束名
       DeleteRule:删除时对应的约束操作
       UpdateRule:更新时对应的约束操作
       更新和删除约束
       Cascade—— 如果更新了父键,就应把新的键值复制到所有的子记录上。如果删除了父记录,也将删除子记录,这是默认选项。
       None—— 不执行任何操作,这个选项会留下子数据表中的孤立行。
       SetDefault—— 如果定义了一个子记录,那么每个受影响的子记录都把外键码列设置为其默认值。
       SetNull—— 所有的子行都把主列设置为DBNull。(按照Microsoft选择的命名约定,主列应是SetDBNull。)
       如:
       DataTable categories = new DataTable("Categories"); //主表
        categories.Columns.Add(new DataColumn("CategoryID", typeof(int)));
        categories.Columns.Add(new DataColumn("CategoryName", typeof(string)));
        categories.Columns.Add(new DataColumn("Description", typeof(string)));
        categories.Constraints.Add(new UniqueConstraint("PK_Categories",categories.Columns["CategoryID"],true));(车延禄)
        DataColumn parent = ds.Tables["Categories"].Columns["CategoryID"];
        DataColumn child = ds.Tables["Products"].Columns["CategoryID"]; //从表中的列
        ForeignKeyConstraint fk = new ForeignKeyConstraint("FK_Product_CategoryID", parent, child);
        fk.UpdateRule = Rule.Cascade;
        fk.DeleteRule = Rule.SetNull;
        ds.Tables["Products"].Constraints.Add(fk);

    数据关系DataRelation
    我们可以在数据集中设置表与表之间的关系,有了表与表之间的关系,我们就可以从子表中取出对应主表中的数据,或从主表中取出对应子表中的数据来
    DataRelation对象属于DataSet而不是属于DataTable。另外,在这里的外键约束也不同于数据关系,外键约束只是为了保证数据集中表的引用完整性,而数据关系是为了实现表和表之间的互访问。
    创建数据关系:
    DataSet ds = new DataSet("Relationships");
       ds.Tables.Add(CreateBuildingTable());(车延禄)
       ds.Tables.Add(CreateRoomTable());
       ds.Relations.Add("Rooms",ds.Tables["Building"].Columns["BuildingID"],ds.Tables["Room"].Columns["BuildingID"]);

    并遍历数据关系,列出Rooms表中所有的子行
      foreach(DataRow theBuilding in ds.Tables["Building"].Rows)
       {
         DataRow[] children = theBuilding.GetChildRows("Rooms");
         foreach(DataRow theRoom in children)
            Console.WriteLine("Room: {0}", theRoom["Name"]);
       }

    数据适配器DataAdapter:
    数据适配器是内存中的数据集与硬盘数据库之间的桥梁,通过数据适配器可以把数据库中的数据加载到内存中的数据集中,也可以把内存中的数据集中修改完的数据更新到数据库去。
    只要我们设置好我们的DataAdapter,我们就可以实现数据集的离线操作。我们可以先把数据库中的相关数据加载到内存的数据集中,然后就可以断开与数据库中的连接,在内存中的数据集对数据进行操作,而不直接提交到数据库中。等到对内存中数据集操作完成后,就可以打开对数据库的链接,把内存中数据集的修改结果一起全更新到数据库中去。这种思路比较适用于移动办公与SmartClient技术。
    SqlDataAdapter对象的实例化:
      SqlDataAdapter SqlAdapter = new SqlDataAdapter();
       在实例化了SqlDataAdapter对象后,此SqlDataAdapter仍然是一个没有实际作用的数据适配器,因为它对数据库和数据集的操作实际上是通过它的四个SqlCommand对象(SelectCommand,InsertCommand,UpdateCommand,DeleteCommand)来实现的。所以我们实例化了SqlDataAdapter对象后需要再实例化它相关的SqlCommand对象
      SqlAdapter.SelectCommand = new SqlCommand();
       SqlAdapter.InsertCommand = new SqlCommand();
       SqlAdapter.UpdateCommand = new SqlCommand();
       SqlAdapter.DeleteCommand = new SqlCommand();
      这四个SqlCommand的引用实际都指向一个SqlCommand对象的实例,我们还需要对每一个SqlCommand对象的相关属性(Connection,CommandType,CommandText,Parameters)进行设置,在此请参照SqlCommand的相关知识
    SqlDataAdapter对象的两个方法:
      Fill(DataSet,string);//SqlDataAdapter自动调用它的SelectCommand对象,查询硬盘数据库,把查询的结果添充到内存数据集中
      Update(DataSet,string);//SqlDataAdapter根据内存数据集中数据的变化情况,自动调用其相应的InsertCommand,DeleteCommand,UpdateCommand把相应的数据更新到硬盘数据库中去。


    使用SqlDataAdapter对象要注意的问题:
      a.SqlDataAdapter对象包含四个SqlCommand对象,这四个SqlCommand对象具有与普通的SqlCommand一样的属性和方法。(车延禄)
       b.SqlDataAdapter对象的实例化需使用new关键字实现,在实例化了SqlDataAdapter对象后会自动产生四个SqlCommand对象的引用,但这四个SqlCommand对象并没有实例化与初始化,需要一一对其实例化与初始化。
       c.SqlDataAdapter对象的Fill()方法会自动调用其SelectCommand对象,Update()方法会自动调用其InsertCommand,UpdateCommand,DeleteCommand。
       d.使用SqlDataAdapter对象操作数据库时不需要显式的打开与关闭连接。Fill()和Update()执行的时候会自动打开与关闭链接。
       e.使用SqlDataAdapter对象操作数据库的实质是SqlDataAdapter对象调用它的四个SqlCommand对象来实现的。
       f.对内存中数据集的操作只能使用DataSet及其子对象的属性与方法来实现,而对数据库操作则要使用Sql语句来实现。
    如:
      private static SqlCommand GenerateSelectCommand(SqlConnection conn )
       {
         SqlCommand aCommand = new SqlCommand("RegionSelect" , conn);
         aCommand.CommandType = CommandType.StoredProcedure;
         aCommand.UpdatedRowSource = UpdateRowSource.None;
         return aCommand;
       }
       DataSet ds = new DataSet();
       SqlDataAdapter da = new SqlDataAdapter();
       da.SelectCommand = GenerateSelectCommand (conn);
       da.Fill(ds , "Region");

    弱类型DataSet与强类型DataSet(车延禄)
    当我们用SqlDataAdapter对象的Fill()方法查询数据时,会自动在内存中的DataSet中创建表并创建相应的列和行,这样创建的DataSet是一个弱类型的。它的数据表中的每个数据都是object类型,虽然object类型的数据可以接受任何数据,但这也正是弱类型的缺陷,由于它对数据类型的限制不严格,会导致里面可以存储错误的数据类型,以致于在更新数据的时候产生错误。另外,它是object类型,在操作数据的时候,往往需要进行拆箱与装箱,而拆箱与装箱的过程对系统资源消耗很大,会从某种程序上降低程序的性能。
    正是由于弱类型的DataSet有上面这些缺陷,我们建议在使用强类型DataSet。所谓的强类型的DataSet,就是事先建立一个派生自DataSet的自定义DataSet,并在其中添加指定的表、列,并指定其表和列的数据类型。然后使用表映射与列映射把它与数据库中的表和列进行对应。这样就不会出现弱类型DataSet所出现的问题了。

    DataSet的问题
    虽然DataSet与SqlDataAdapter二者对数据库的操作可以称之谓“最佳拍档”,是ADO.NET中新增的数据访问方式。但对大部分开发人员来说,对这种数据访问并不太看好。其中一个很大的原因,就是这种DataSet是把数据库中的二维表再加载到内存中的二维表。这种内存中的二维表并不总适合于“对象世界”的程序代码,在对于复杂的业务逻辑它处理起来往往显得笨拙复杂。所以我们往往更倾向于实体类与泛型集合结合来实现数据访问,或者把DataSet与实体类进行结合进行数据操作,关于实体类和泛型集合的设计与使用,在下一篇中进行阐述。

  • 相关阅读:
    链表--判断一个链表是否为回文结构
    矩阵--“之”字形打印矩阵
    二叉树——平衡二叉树,二叉搜索树,完全二叉树
    链表--反转单向和双向链表
    codeforces 490C. Hacking Cypher 解题报告
    codeforces 490B.Queue 解题报告
    BestCoder19 1001.Alexandra and Prime Numbers(hdu 5108) 解题报告
    codeforces 488A. Giga Tower 解题报告
    codeforces 489C.Given Length and Sum of Digits... 解题报告
    codeforces 489B. BerSU Ball 解题报告
  • 原文地址:https://www.cnblogs.com/hateyoucode/p/1359957.html
Copyright © 2011-2022 走看看