• C# 数据操作系列


    0. 前言

    在上一篇中,我故意留下了查询的示范没讲。虽然说可以通过以下代码获取一个DataReader:

    IDataReader reader = command.ExecuteReader();
    

    然后通过reader一行一行的读取数据,但是我并不推荐这样使用。

    在查询这一高频需求上,C#为之做了很多工作,提供了更多的选择。这里介绍一个查询的另一套写法。

    1. 离线查询

    C#在查询上提供了另一种机制,可以一次性从数据库把结果读取到网络缓存区中,直到使用的时候才加载到程序中。

    在离线查询里最关键的三个接口或类:

    • IDataAdapter 一种适配器,用来获取数据并填充或更新DataSet
    • DataSet 表示数据在内存中的缓存
    • DataTable 表示内存中一个数据表

    IDataAdapter用来提供数据,DataSet表示adapter读取的结果集,其中有一个DataTable集合表示执行的SQL查询结果。至于为什么是集合,是因为IDataAdapter允许运行多条查询语句。

    好,让我们粗略浏览一下这个三个关键点的属性和方法:

    IDataAdapter:

    public int Fill (System.Data.DataSet dataSet);//将查询出来的结果填充到DataSet里
    

    在C#内部,其实不允许推荐直接继承该接口,推荐继承DataAdapter类,该类规定了数据库Adapter在初始化的时候,必须提供一个可以访问的数据库连接和要执行的命令文本。

    当然其部分实现类允许以属性的形式后赋值这两个关键内容。

    DataSet:

    public DataSet ();
    public DataSet (string dataSetName);//指定数据集的名称
    public System.Data.DataTableCollection Tables { get; }//获取包含在 DataSet 中的表的集合
    

    DataSet有很多有用的方法,但是在今天我们只用关系这些就可以了。

    其中Tables 引入了一个没有提到的类型,DataTableCollection。那么我们可以顺藤摸瓜,来看看里面有什么关键的内容:

    public System.Data.DataTable this[int index] { get; }// 获取指定下标的DataTable
    public System.Data.DataTable this[string name] { get; }//获取具有指定名称的DataTable
    

    可以看到提供了一种我们可以获取到里面的DataTable元素的索引访问方式。

    DataTable :

    public System.Data.DataSet DataSet { get; }//获取此表所属的 DataSet。
    public System.Data.DataColumnCollection Columns { get; }//获取属于该表的列的集合
    public System.Data.DataRowCollection Rows { get; }//获取属于该表的行的集合
    

    又出现了两个新的类:DataColumnCollection、DataRowCollection。这是一种内部集合的实现类,功能类似于List,但又不等同于List。

    我们大概看一下对我们有用的属性和方法:

    DataColumnCollection:

    public virtual int Count { get; }//获取集合中的元素总数
    public System.Data.DataColumn this[int index] { get; }//从集合中获取位于指定索引位置的 DataColumn
    public System.Data.DataColumn this[string name] { get; }//从具有指定名称的集合中获取 DataColumn。
    

    DataRowCollection:

    public override int Count { get; }
    public System.Data.DataRow this[int index] { get; }// 获取索引处的行
    

    嗯,好先到此为止。调转方向回到上个路口,重新来。让我们看看DataColumn和DataRow又有哪些值得我们现在关注的:

    DataColumn:

    public string ColumnName { get; set; }//获取或设置 DataColumnCollection 中的列的名称
    public Type DataType { get; set; }//获取或设置存储在列中的数据的类型
    

    DataRow:

    public object this[System.Data.DataColumn column] { get; set; }//获取或设置指定 DataColumn 中存储的数据
    public object this[int columnIndex] { get; set; }//获取或设置由索引指定的列中存储的数据
    public object this[string columnName] { get; set; }//获取或设置由名称指定的列中存储的数据
    public object[] ItemArray { get; set; }//通过数组获取或设置此行的所有值
    

    到目前为止,离线查询的支持类和接口就介绍了个大概。那么我们看看如何进行一个离线查询吧

    2.实践看看

    以SQL Server数据库为例:

    获取一个SqlDataAdapter,C#提供了四种方式获取:

    public SqlDataAdapter ();//构造一个没有连接和命令的Adapter对象
    public SqlDataAdapter (System.Data.SqlClient.SqlCommand selectCommand);// 指定一个查询命令
    public SqlDataAdapter (string selectCommandText, System.Data.SqlClient.SqlConnection selectConnection);//指定查询命令,和连接
    public SqlDataAdapter (string selectCommandText, string selectConnectionString);//指定查询命令和连接字符串
    

    引用命名空间:

    using System.Data;
    using System.Data.SqlClient;
    

    那么,我们先构造一个Adapter:

    var connectStr = "Data Source=.;Initial Catalog=Old;Integrated Security=True";
    var sql = "select * from Area_PostCode";
    var adapter = new SqlDataAdapter(sql, connectStr);
    

    然后创建一个用于保存数据的DataSet,并把数据填充进去:

    DataSet set = new DataSet();
    adapter.Fill(set);
    

    然后可以看到这个set中的数据应该是这样的:

    image-20200512004118597

    上图是在VS中的调试模式中,可以看到

    根据上图我们大概可以猜测一下DataTable内部的数据结构,或者C#让我们理解的结构是什么。

    其中DataColumn对应着图中列,ColumnName就是图 所示的列名。而DataRow就是行,ItemArray则是一行行数据。

    这样一来,显然就比直接使用IDataReader访问数据要方便很多。

    依据上例:

    我们试着获取一下第三行的Province列值,如果觉得这个表述别扭的话,看一下我的写法,就知道我为什么这么表示了。

    var table = set.Tables[0];// 先拿到第一个表
    var value = table.Rows[2]["Province"];
    

    这是一种蚂蚁搬家式的读取数据方式。C#为DataTable提供了一个扩展方法:

    public static EnumerableRowCollection<DataRow> AsEnumerable(this DataTable source);
    

    将表格转换成可枚举的DataRow集合。

    所以我们可以用foreach循环来遍历DataTable。

    3. 未完待续

    在这一节简单介绍了一下ADO.NET的离线查询支持。当我们能从数据库中获取到DataTable的时候,我们就能通过这个做出更多的事情来。下一章我将带领大家结合之前介绍的反射,实现一个简单的ORM工具类。

    更多内容烦请关注我的博客《高先生小屋》

    file

  • 相关阅读:
    IO流总览图
    自己实现的一个数组排序并去重的功能
    Java常量池详解之一道比较蛋疼的面试题
    一个简单的数组去重并排序方法
    Delphi开发经验谈
    再谈Delphi vs VC++(非常精彩)
    C#根据当前时间获取,本周,本月,本季度等时间段
    delphi CopyMemory、FillMemory、MoveMemory、ZeroMemory
    DupeString 与 StringOfChar 的区别
    SQL最大值加1
  • 原文地址:https://www.cnblogs.com/c7jie/p/12874317.html
Copyright © 2020-2023  润新知