ado.net_sqlcommad

一.创建sqlcommand对象的三种方法:

1.有参:

SqlCommand cmd=new SqlCommand(sql,conn);

2.无参:

SqlCommand cmd=new SqlCommand();

利用cmd对象属性:

cmd.Connection=conn;

cmd.CommandText=sql;

利用conn对象属性:

cmd=con.CreateCommand();

cmd.CommandText=sql;

 

二.SqlCommand执行sql语句

1.进行dml操作

cmd.ExecuteNonQuery;

int total=cmd.ExecuteNonQuery;//用于显示受影响总行数

如果批量sql语句执行时,要显示受影响行数,则使用cmd.StatementCompleted属性。

 SqlCommand cmd=new SqlCommand(sql,conn);//有参构造
 cmd.StatementCompleted+=new StatementCompletedEventHandler(showrs);

void showrs(Object sender,StatementCompletedEventArgs e)
{
    Response.Write("Every Row is:"+e.RecordCount.ToString()+"\r\n");
}

 

3.进行读取操作
SqlDataReader dr=cmd.ExecuteReader();

bool hasrows=dr.HasRows;

while(dr.Read())

{

    Response.Write(dr[0]);//顺序读取某一列的全部值

}

如果只读取第一列第一行的值的话,使用cmd.ExecuteSalar()属性,返回一个Object对象。

Object  rs=cmd.ExecuteSalar();

 

4.进行事务操作:用using 其cmd对象包围即可

 conn.Open();
   using(SqlTransaction tst=conn.BeginTransaction()){
   SqlCommand cmd=new SqlCommand(sql,conn,tst);//有参构造  
   try
   {
    int total=cmd.ExecuteNonQuery();
   
    Response.Write("total is:"+total.ToString());
    tst.Commit();
   }
   catch(Exception ee)
   {
    tst.Rollback();
    Response.Write(ee.Message);
   
   }
   }
   conn.Close();

 

4.异步操作:

异步执行查询

在ADO.NET 2.0中,SqlCommand现在提供对异步查询的支持。一些查询总是立即返回;而另外一些查询则会需要一点时间来执行。如果正在处理可能需要一点时间来执行的查询,并且希望在SQL Server处理该查询时执行其他任务,那么请考虑使用异步查询。这一特性对于SQL Server 2005,SQL Server 2000和SQL Server 7.0均有效。

为什么会希望异步执行一个查询呢?在使用标准异步模式执行查询时,在SQL Server处理查询并在结果集中返回第一可用行之后,该调用才会完成。在等待SQL Server响应时,可能还希望执行其他操作,例如对另一数据库进行查询,或者调用Web服务以获取其他         信息。

如果正在使用.NET Framework中的其他异步特性,SqlCommand类对异步查询的支持看起来有些类似。SqlCommand类为ExecuteReader,ExecuteNonQuery和ExecuteXmlReader方法公开了Begin和End方法。例如有一个BeginExecuteReader方法和一个EndExecuteReader方法。

每个Begin方法返回一个实现IAsyncResult接口的对象。这一返回对象是查询状态的一个句柄。IAsyncResult接口是用于异步方法的.NET Framework模式的一部分,其设计目的是:帮助确定该操作是否已经完成;如果需要等待该操作完成则中断当前线程;用作方法调用结果的句柄。在随后的例子中说明如何使用SqlCommand异步执行查询,还将说明IAsyncResult接口的这些特性。

为了在例子中模拟一个长时间运行的查询,首先以SQL Server“WAITFOR DELAY”查询执行一个简单查询。以下查询在返回Customers表的内容之前等待10秒。

WAITFOR DELAY '00:00:10'; SELECT * FROM Customers

异步特性在默认情况下未被启用。要启用SqlConnection的异步查询,请在连接字符串中包括以下内容:

Asynchronous Processing=True;

 提示    与其他连接字符串选项一样,如果在记忆关键字时存在困难,SqlConnectionStringBuilder可以提供帮助。

1. 异步执行查询并等待结果

假定我们希望异步执行一个查询,执行一系列其他操作。在这些操作完成之后,将一直等待,直到这些结果可用为止。以下代码示例引用了System.Threading命名空间(使用using或Imports,取决于您所选择的语言)。

Visual Basic

Dim strConn, strSQL As String

strConn = "Data Source=.\SQLExpress;" & _

            "Initial Catalog=Northwind;Trusted_Connection=Yes;" & _

            "Asynchronous Processing=True;"

strSQL = "WAITFOR DELAY '00:00:10'; SELECT * FROM Customers"

Dim cn As New SqlConnection(strConn)

cn.Open()

Dim cmd As New SqlCommand(strSQL, cn)

Dim iar As IAsyncResult = cmd.BeginExecuteReader()

'执行其他操作

Dim rdr As IAsyncResult = cmd.EndExecuteReader(iar)

Do While rdr.Read()

    Console.WriteLine(rdr("CustomerID"))

Loop

rdr.Close()

cn.Close()

Visual C#

string strConn, strSQL;

strConn = @"Data Source=.\SQLExpress;" +

             "Initial Catalog=Northwind;Trusted_Connection=Yes;" +

             "Asynchronous Processing=True;";

strSQL = "WAITFOR DELAY '00:00:10'; SELECT * FROM Customers";

SqlConnection cn = new SqlConnection(strConn);

cn.Open();

SqlCommand cmd = new SqlCommand(strSQL, cn);

IAsyncResult iar = cmd.BeginExecuteReader();

//执行其他操作

SqlDataReader rdr = cmd.EndExecuteReader(iar);

while (rdr.Read())

    Console.WriteLine(rdr["CustomerID"]);

rdr.Close();

cn.Close();

可以检查IAsyncResult接口的IsCompleted属性,以查看BeginExecuteReader调用是否已经完成。如果发出了多个异步请求,并希望知道哪些请求已经完成并首先处理其结果,那么这一检查可能很有帮助。在此情况下,如果对BeginExecuteReader的调用尚未完成,则没有其他要执行的工作。所以无论如何都将等待该调用完成,而且这也是End方法的默认行为。如果调用一个End方法,它在Begin方法完成之前不会返回。

还可以通过调用IAsyncResult.AsyncWaitHandle.WaitOne,使用IAsyncResult接口来等待该调用完成。调用一个带有参数的WaitOne方法可以使您等待指定的时间(以毫秒为单位),然后检查IsCompleted方法,以确定该调用是否已经完成。利用WaitOne方法,可以构造“AreWeThereYet”逻辑,在此逻辑中,代码每三秒询问一次该操作是否已经完成,如以下代码所示:

Visual Basic

...

Dim iar As IAsyncResult = cmd.BeginExecuteReader()

Console.Write("Are we there yet? ")

Do While Not iar.IsCompleted

    Console.WriteLine("No!")

    iar.AsyncWaitHandle.WaitOne(3000, True)

    Console.Write("Are we there yet? ")

Loop

Console.WriteLine("Yes!")

Visual C#

...

IAsyncResult iar = cmd.BeginExecuteReader();

Console.Write("Are we there yet? ");

while (!iar.IsCompleted) {

    Console.WriteLine("No!");

    iar.AsyncWaitHandle.WaitOne(3000, true);

    Console.Write("Are we there yet? ");

}

Console.WriteLine("Yes!");

2. 异步执行多个查询并等待其中一个查询完成

一种更有帮助的异步查询方案涉及ASP.NET页,ASP.NET页需要对多个数据执行查询。使用多个SqlCommand的异步方法,可以异步发出一系列查询。然后可以使用上例中所描述的WaitOne方法来等待一特定查询完成。

但是,您是否真正知道哪个查询将首先完成呢?可以根据执行查询的顺序来处理结果,但是否能够保证第一个执行的查询就是第一个完成的查询呢?如果按照这一顺序处理结果,而第二个查询先于第一个查询完成,那么就不能尽快为页面提供服务。

一种功能更强大的选项是使用.NET Framework的Threading特性,并等待查询中的任何一个完成。System.Threading命名空间中的WaitHandle类公开一个静态WaitAny方法和一个静态WaitAll方法,以帮助处理这种类型的情景。这些方法分别接受一个WaitHandle的数组。在任意一个与这些WaitHandle相关联的异步操作完成之后,WaitAny方法立即返回。WaitAll方法的行为与此相同,只是它要等待所有异步操作均完成。

在稍后的例子中将使用WaitAny方法。

3. 将附加状态传递给Begin方法

Begin方法包括可以在StateObject参数中进行传递的重载。这一参数接受任何对象,并将这一对象分配给所得到的IAsyncResult接口的AsyncState属性。

以下代码段说明如何在代码中使用这一特性。此代码段打开两个SqlConnection——一个用于获取客户信息,一个用于获取订单信息。它们使用同一连接字符串简化该情景。在实际应用程序中,它们可以使用同一SQL Server或不同SQL Server。该代码对每一个SqlConnection执行异步查询。有趣之处自此而始!

一旦该代码异步执行两个查询,它会使用WaitHandle类的WaitAny方法等待两个查询中的任意一个完成。WaitAny方法接受WaitHandle的一个数组,并返回其操作已经完成的WaitHandle的索引。这里的挑战在于确定索引的含义。哪个查询完成了?返回客户消息的那个查询还是返回订单信息的那个查询?

一种方法是硬编码,数组中的第一项对应于客户查询,数组中的第二项对应于订单查询。然后可以在Case或switch代码块中检查WaitAny的返回值,以确定将调用其EndExecuteReader方法的SqlCommand。

第二种方法是将一些附加状态信息传递给BeginExecuteReader方法。可以将诸如Customers和Orders等字符串传递给BeginExecuteReader方法。在此代码段中,将实际SqlCommand对象传递给BeginExecuteReader方法。采用这一方法,可以通过IAsyncResult对象的AsyncState属性使用SqlCommand对象。因此,当WaitAny调用返回时,我们访问相应的IAsyncResult对象,并且只是将AsyncState属性转换为SqlCommand,处理该结果,并关闭SqlCommand的Connection。

Visual Basic

'Imports System.Threading

Dim strConn, strSQL As String

Dim cnCustomers, cnOrders As SqlConnection

Dim cmdCustomers, cmdOrders As SqlCommand

Dim iasyncresults(1) As IAsyncResult()

Dim waithandles(1) As WaitHandle()

strConn = "Data Source=.\SQLExpress;" & _

            "Initial Catalog=Northwind;Integrated Security=True;" & _

            "Asynchronous Processing=True;"

cnCustomers = New SqlConnection(strConn)

cnCustomers.Open()

cnOrders = New SqlConnection(strConn)

cnOrders.Open()

strSQL = "WAITFOR DELAY '00:00:10'; " & _

           "SELECT TOP 10 CustomerID FROM Customers"

cmdCustomers = New SqlCommand(strSQL, cnCustomers)

iasyncresults(0) = cmdCustomers.BeginExecuteReader(Nothing, cmdCustomers, _

                                                           CommandBehavior.

                                                           CloseConnection)

waithandles(0) = iasyncresults(0).AsyncWaitHandle

strSQL = "WAITFOR DELAY '00:00:05'; SELECT TOP 10 OrderID FROM Orders"

cmdOrders = New SqlCommand(strSQL, cnOrders)

iasyncresults(1) = cmdOrders.BeginExecuteReader(Nothing, cmdOrders, _

                                                       CommandBehavior.
                                                       CloseConnection)

waithandles(1) = iasyncresults(1).AsyncWaitHandle

For intCounter As Integer = 0 To waithandles.Length – 1

    Dim intIndex As Integer = WaitHandle.WaitAny(waithandles)

    Dim cmd As SqlCommand

    cmd = CType(iasyncresults(intIndex).AsyncState, SqlCommand)

    Console.WriteLine(cmd.CommandText)

    Using rdr As SqlDataReader _

               = cmd.EndExecuteReader(iasyncresults(intIndex))

        Do While rdr.Read()

            Console.WriteLine(rdr(0))

        Loop

        rdr.Close()

    End Using

Next intCounter

Visual C#

//using System.Threading;

string strConn, strSQL;

SqlConnection cnCustomers, cnOrders;

SqlCommand cmdCustomers, cmdOrders;

IAsyncResult[] iasyncresults = new IAsyncResult[2];

WaitHandle[] waithandles = new WaitHandle[2];

strConn = @"Data Source=.\SQLExpress;" +

             "Initial Catalog=Northwind;Integrated Security=True;" +

             "Asynchronous Processing=True;";

cnCustomers = new SqlConnection(strConn);

cnCustomers.Open();

cnOrders = new SqlConnection(strConn);

cnOrders.Open();

strSQL = "WAITFOR DELAY '00:00:10'; " +

           "SELECT TOP 10 CustomerID FROM Customers";

cmdCustomers = new SqlCommand(strSQL, cnCustomers);

iasyncresults[0] = cmdCustomers.BeginExecuteReader(null, cmdCustomers,

                                                          CommandBehavior.
                                                          CloseConnection);

waithandles[0] = iasyncresults[0].AsyncWaitHandle;

strSQL = "WAITFOR DELAY '00:00:05'; SELECT TOP 10 OrderID FROM Orders";

cmdOrders = new SqlCommand(strSQL, cnOrders);

iasyncresults[1] = cmdOrders.BeginExecuteReader(null, cmdOrders,

                                                       CommandBehavior.

                                                       CloseConnection);

waithandles[1] = iasyncresults[1].AsyncWaitHandle;

for (int intCounter = 0; intCounter < waithandles.Length; intCounter++)

{

    int intIndex = WaitHandle.WaitAny(waithandles);

    SqlCommand cmd = (SqlCommand) iasyncresults[intIndex].AsyncState;

    Console.WriteLine(cmd.CommandText);

    using (SqlDataReader rdr =

                            cmd.EndExecuteReader(iasyncresults[intIndex]))

    {

        while (rdr.Read())

            Console.WriteLine(rdr[0]);

        rdr.Close();

    }

}

 提示    以上代码段在执行查询时使用CommandBehavior.CloseConnection。当在对ExecuteReader(或BeginExecuteReader)的调用中指定这一选项时,关闭所得到的SqlDataReader还将关闭相应的SqlConnection。使用CommandBehavior. CloseConnection可以帮助编写更可靠的代码,特别是当使用SqlDataReader的代码不能访问SqlConnection时。

4. 用回滚函数异步执行查询

您可能已经注意到,在上述代码段中,没有向BeginExecuteReader的第一个参数传递数据。这一重载中第一个参数接收一个回滚函数。如果向这一方法中传递一个回滚函数,当异步操作完成时将调用此函数。然后,您可以从函数之内调用EndExecuteReader方法。如需有关回滚函数的详细信息,请参阅.NET Framework软件开发工具包(SDK)。

以下代码说明回滚函数的使用。与其他示例不同,这一个示例不是用于基本的控制台应用程序。如果在控制台应用程序中运行此代码,“主”代码将在查询完成之前完成,该应用程序会在调用回滚函数之前结束。为了更好地理解这一情景,创建一个Windows应用程序,向窗体中添加一个按钮,将主代码复制到按钮的Click事件中,并在调用EndExecuteReader的位置设置一个断点。单独复制MyCallback函数,并在调用EndExecuteReader的位置设置一个断点,然后运行该代码。将会看到,在调用BeginExecuteReader之后大约10秒调用该回滚函数,这个时间延迟是在查询中指定的。

Visual Basic

Dim strConn, strSQL As String

strConn = "Data Source=.\SQLExpress;" & _

            "Initial Catalog=Northwind;Integrated Security=True;" & _

            "Asynchronous Processing=True;"

Dim cn As New SqlConnection(strConn)

cn.Open()

strSQL = "WAITFOR DELAY '00:00:10'; " & _

           "SELECT TOP 10 CustomerID FROM Customers"

Dim cmd As New SqlCommand(strSQL, cn)

Dim callback As New AsyncCallback(AddressOf MyCallback)

cmd.BeginExecuteReader(callback, cmd, CommandBehavior.CloseConnection)

Private Sub MyCallback(ByVal Result As IAsyncResult)

    Dim cmd As SqlCommand = CType(Result.AsyncState, SqlCommand)

    Using rdr As SqlDataReader = cmd.EndExecuteReader(Result)

        Do While rdr.Read()

            Console.WriteLine(rdr(0))

        Loop

        rdr.Close()

    End Using

End Sub

Visual C#

string strConn, strSQL;

strConn = @"Data Source=.\SQLExpress;" +

             "Initial Catalog=Northwind;Integrated Security=True;" +

             "Asynchronous Processing=True;";

SqlConnection cn = new SqlConnection(strConn);

cn.Open();

strSQL = "WAITFOR DELAY '00:00:10'; " +

           "SELECT TOP 10 CustomerID FROM Customers";

SqlCommand cmd = new SqlCommand(strSQL, cn);

AsyncCallback callback = new AsyncCallback(MyCallback);

cmd.BeginExecuteReader(callback, cmd, CommandBehavior.CloseConnection);

private void MyCallback(IAsyncResult result)

{

    SqlCommand cmd = (SqlCommand)result.AsyncState;

    using (SqlDataReader rdr = cmd.EndExecuteReader(result))

    {

        while (rdr.Read())

            Console.WriteLine(rdr[0]);

        rdr.Close();

    }

}

异步查询和Windows应用程序  我已经和许多开发人员就ADO.NET的新异步特性进行了讨论。他们在想到为Windows应用程序使用回滚函数时通常会非常高兴。但是,在Windows应用程序中使用这一方法所带来的问题可能多于带来的好处。

在以上代码示例中,我们使用一个称为MyCallback的函数来处理查询的结果。这一过程在后台线程中执行,这意味着如果尝试与来自该过程内的用户接口进行交互,就会存在严格的限制。例如,如果将查询结构加载到DataTable中,然后尝试将DataGridView绑定到DataTable,将会接收到一个InvalidOperationException,其说明只能从创建该控件的线程之内访问它。

可以从回滚函数中创建并调用一个委托,以与这些控件进行交互。事实上,在.NET Framework SDK中有一个主题说明了这种方法,并且更深入地对委托进行了讨论。到编写本书时为止,可以在文档中找到关于BeginExecuteReader方法重载的示例,这一方法以回滚函数为参数。

一种更简单的方法是使用.NET Framework 2.0中用于Windows窗体的一个新特性——BackgroundWorker类。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值