• 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与实体类进行结合进行数据操作,关于实体类和泛型集合的设计与使用,在下一篇中进行阐述。

  • 相关阅读:
    eclipse开发安卓 发短信打电话发送邮件功能
    关于springboot连接数据库是报错
    --Angular-01-关于angular-tree-component--
    --外功篇-Less的学习日志-01-辅助理解Less--
    --兵器谱--git学习记录帖--
    --兵器谱--git初体验--
    --算法恩仇录--实战篇--力扣(LeetCode)--022-括号生成--
    --算法恩仇录--实战篇--力扣(LeetCode)--011-盛水最多的容器--
    --算法恩仇录--实战篇--力扣(LeetCode)--006-Z字形变换--
    --算法恩仇录--实战篇--力扣(LeetCode)--005-最长回文子串--
  • 原文地址:https://www.cnblogs.com/hateyoucode/p/1359957.html
Copyright © 2020-2023  润新知