ADO.NET与抽水的故事 系列四——输水管——DataAdapter

 趣味理解ADO.NET对象模型

输水管——DataAdapter

DataAdapter提供连接DataSet对象和数据源的桥梁。DataAdapter使用Command对象在数据源中执行SQL命令,以便将数据加载到DataSet中,并使DataSet中数据的更改与数据源保持一致。

趣味理解

DataAdapter就像一根输水管,通过发动机,把水从水源输送到水库里进行保存。

1.创建SqlDataAdapter

(1)初始化SqlDataAdapter类的新实例。

string conString = "data source=127.0.0.1;Database=codematic;user id=sa;

        password=";

SqlConnection myConnection = new SqlConnection(conString);

SqlCommand cmd = myConnection.CreateCommand();

cmd.CommandText = "SELECT * FROM P_Product";

DataSet ds = new DataSet();

myConnection.Open();

SqlDataAdapter adapter = new SqlDataAdapter();

adapter.SelectCommand = cmd;

adapter.Fill(ds, "ds");

myConnection.Close();

(2)使用指定的 SqlCommand 初始化 SqlDataAdapter 类的新实例。

string conString = "data source=127.0.0.1;Database=codematic;user id=sa;

        password=";

SqlConnection myConnection = new SqlConnection(conString);

DataSet ds = new DataSet();

SqlCommand cmd = myConnection.CreateCommand();

cmd.CommandText = "SELECT * FROM P_Product";

myConnection.Open();

SqlDataAdapter adapter = new SqlDataAdapter(cmd);

adapter.Fill(ds, "ds");

myConnection.Close();

(3)使用selectcommand字符串 和 SqlConnection对象初始化SqlDataAdapter 类的新实例。

string conString = "data source=127.0.0.1;Database=codematic;user id=sa;

password=";

string strSQL = "SELECT * FROM P_Product";

SqlConnection myConnection = new SqlConnection(conString);

DataSet ds = new DataSet();

myConnection.Open();

SqlDataAdapter adapter = new SqlDataAdapter(strSQL, myConnection);

adapter.Fill(ds, "ds");

myConnection.Close();

(4)使用selectcommand字符串和一个连接字符串初始化SqlDataAdapter类的新实例。

string conString = "data source=127.0.0.1;Database=codematic;user id=sa;

password=";

string strSQL = "SELECT * FROM P_Product";           

DataSet ds = new DataSet();           

SqlDataAdapter adapter = new SqlDataAdapter(strSQL, conString);

adapter.Fill(ds, "ds");

2.DataAdapter和SqlConnection、SqlCommand建立关联

方式1:DataAdapter在构造参数时建立。

方式2:通过SelectCommand属性建立。

SqlDataAdapter adapter = new SqlDataAdapter();

adapter.SelectCommand = new SqlCommand(strSQL, myConnection);

5.1.6  输水管——DataReader

通过执行ExecuteReader方法可以返回一个DataReader 对象。DataReader以只进、只读方式返回数据,从而提高应用程序的性能。这样可以节省 DataSet 所使用的内存,并省去创建 DataSet 并填充其内容所需的处理。

趣味理解

DataReader 也是一种水管,和DataAdapter不同的是,DataReader不把水输送到水库里面,而是单向地直接把水送到需要水的用户那里或田地里,所以要比在水库中转一下更快。

(1)遍历DataReader结果集。

SqlDataReader dr = cmd.ExecuteReader();           

while (dr.Read())

{

    Response.Write(dr.GetInt32(0).ToString()+ ", "+ dr.GetString(1) + "
");

}

dr.Close();

(2)使用序数索引器。

SqlDataReader dr = cmd.ExecuteReader();

while (dr.Read())

{

    Response.Write(dr[0].ToString() + ", " + dr[1].ToString() + "
");

}

dr.Close();

(3)使用列名索引器。

SqlDataReader dr = cmd.ExecuteReader();

while (dr.Read())

{

    Response.Write(dr["ProductId"].ToString()+", "+dr["Name"].ToString());

}

dr.Close();

(4)使用类型访问器。

public char GetChar(int i); 获取指定列的单个字符串形式的值

public DateTime GetDateTime(int i); 获取指定列的 DateTime 对象形式的值

public short GetInt16(int i); 获取指定列的 16 位有符号整数形式的值

public string GetString(int i); 获取指定列的字符串形式的值

(5)得到DataReader的列信息。

dr.FieldCount     获取当前行中的列数

dr.GetFieldType(序号)   获取是对象的数据类型的 Type

dr.GetDataTypeName(序号)  获取源数据类型的名称

dr.GetName(序号)     获取指定列的名称

dr.GetOrdinal(序号)   在给定列名称的情况下获取列序号

(6)得到数据表的信息。

DataTable dt=dr.GetSchemaTable();

(7)操作多个结果集。

SqlDataReader dr = cmd.ExecuteReader();    

do

{

    while (dr.Read())

    {

        Response.Write(dr.GetInt32(0).ToString()+", "+dr.GetString(1));

    }

}

while(myReader.NextResult());//使数据读取器前进到下一个结果集

dr.Close();

下面是一些使用DataReader获得最佳性能的技巧。

l         在使用带参数的Command前,必须关闭DataReader。

l         完成读数据之后一定要关闭DataReader。如果使用Connection只返回DataReader,那么关闭DataReader之后立刻关闭它。另外一个显式关闭Connection的方法是将CommandBehavior.CloseConnection传递给ExecuteReader方法,以确保关闭DataReader时相应的连接也被关闭。如果从一个方法返回DataReader,而且不能控制DataReader的相关连接的关闭,则这样做特别有用。

l         不能在层之间远程访问DataReader。DataReader是为已连接好的数据访问而设计的。

l         当访问列数据时,使用类型化访问器,例如GetString、GetInt32等。这使你不用将GetValue返回的Object强制转换成特定类型。

l         一个单一连接每次只能打开一个DataReader。如果想在相同的数据存储区上同时打开两个DataReader,则必须显式创建两个连接,每个DataReader一个。这是ADO.NET为池化连接的使用提供更多控制的一种方法。

l         在默认情况下,DataReader每次Read时都要将整行加载到内存。这允许在当前行内随机访问列。如果不需要这种随机访问,为了提高性能,则将CommandBehavior.SequentialAccess传递给ExecuteReader调用。这将DataReader的默认行为更改为仅在请求时将数据加载到内存。注意,CommandBehavior. SequentialAccess要求顺序访问返回的列。也就是说,一旦读过返回的列,就不能再读它的值了。

l         如果已经读取了来自DataReader的数据,但仍然有大量挂起的未读结果,则在关闭DataReader之前先要取消Command。因为取消Command可使服务器放弃这些结果,从而释放服务器的资源。

5.1.7  随用随关,释放资源

对于C#程序员来说,确保始终关闭Connection和DataReader对象的一个方便的方法就是使用using语句。using语句在离开自己的作用范围时,会自动调用被“使用”的对象的Dispose。例如:

string connectionString = "data source=127.0.0.1;Database=codematic;

user id=sa;password=";

using (SqlConnection myConnection = new SqlConnection(connectionString))

{

    SqlCommand cmd = myConnection.CreateCommand();

    cmd.CommandText = "SELECT * FROM P_Product";

    myConnection.Open();

    using (SqlDataReader dr = cmd.ExecuteReader())

    {

        while (dr.Read())

        {

            Response.Write(dr.GetInt32(0).ToString()+","+dr.GetString(1)+"
");

        }

}

}

 

 

本文出自《亮剑.NET. .NET深入体验与实战精要》一书

《亮剑.NET: .NET深入体验与实战精要》

请使用浏览器的分享功能分享到微信等