Multiple Active Result Sets (MARS) in ADO.NET 2.0 and SQL Server 2005

本文介绍了ADO.NET 2.0中的Multiple Active Result Sets (MARS)特性,该特性允许通过单一连接同时打开多个结果集并并发访问。文章通过一个示例演示了如何启用MARS,并详细解释了使用MARS创建ASP.NET页面的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Multiple Active Result Sets (MARS) in ADO.NET 2.0 and SQL Server 2005<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

Posted by Rickie Lee, http://rickie.cnblogs.com

Multiple Active Result Sets (MARS) is a new feature of ADO.NET 2.0 that provides the capability to open more than one result set over the same connection and lets you access them all concurrently. Prior to MARS, each result set required a separate connection. Currently, the first commercial database to support MARS is SQL Server 2005.

 

1. Enable MARS by setting MultipleActiveResultSets=True in the connection string

<connectionStrings>

      <add name="Northwind" connectionString="Server=localhost; Database=Northwind; User ID=sa; Password=developer; MultipleActiveResultSets=True" />

</connectionStrings>

 

Otherwise, you will get the following exception.

"Systerm.InvalidOperationException: There is already an open DataReader associated with this connection which must be closed first".

 

This setting only has an effect when used with SQL Server 2005 or a later version.

 

2. Follow these steps to create a demo web page.

(1) Retrieve the Order result set using a SqlDataReader object and binds it to a GridView control.

(2) Set up the OnRowDataBound property of the GridView control.

        <asp:GridView ID="gvOrders" Runat="server" AutoGenerateColumns="False"

                OnRowDataBound="gvOrders_RowDataBound" Width="100%">

When the GridView control starts to bind the DataReader, it starts firing the OnRowDataBound event for each record.

 

(3) Create an OnRowDataBound event handler.

In the method, we can get reference to each DataReader record by using the IDataRecord interface, then access the specified column and get the value. Finally, we retrieve the database again over the same SQL connection.

        IDataRecord OrderRecord;

 

        // Retrieving the currently bound record from the Data Reader

        // using the IDataRecord interface

        OrderRecord = e.Row.DataItem as IDataRecord;

 

        // Retrieving reference to the Label Control inside the current

        // GridView row. This Label will be populated with Order Details

        lblOrderDetail = e.Row.FindControl("lblOrderDetail") as Label;

 

        if ((OrderRecord == null) || (lblOrderDetail == null))

            return;

      ………………………………………        

 

 

The following full code of the ASPX page is abstracted from the reference 1. Please get more detail information in the book.

 

None.gif <% @ Page Language = " C# "   %>
None.gif
<% @ Import Namespace = " System.Data "   %>
None.gif
<% @ Import Namespace = " System.Data.SqlClient "   %>
None.gif
<% @ Import Namespace = " System.Configuration "   %>
None.gif
None.gif
< script runat = " server " >
None.gif    
//  Declaring connection here allows us to use it inside all methods 
None.gif    
//  of this class
None.gif
    SqlConnection DBCon;
None.gif     
None.gif    
protected   void  Page_Load( object  sender, EventArgs e)
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif
InBlock.gif        SqlCommand Command 
= new SqlCommand();
InBlock.gif        SqlDataReader OrdersReader;
InBlock.gif
InBlock.gif        DBCon 
= new SqlConnection();
InBlock.gif        DBCon.ConnectionString 
= ConfigurationManager.ConnectionStrings["Northwind"].ConnectionString;
InBlock.gif
InBlock.gif        Command.CommandText 
=
InBlock.gif                
" SELECT TOP 100 Customers.CompanyName, Customers.ContactName, " +
InBlock.gif                
" Orders.OrderID, Orders.OrderDate, " +
InBlock.gif                
" Orders.RequiredDate, Orders.ShippedDate " +
InBlock.gif                
" FROM Orders, Customers " +
InBlock.gif                
" WHERE Orders.CustomerID = Customers.CustomerID " +
InBlock.gif                
" ORDER BY Customers.CompanyName, Customers.ContactName ";
InBlock.gif
InBlock.gif        Command.CommandType 
= CommandType.Text;
InBlock.gif        Command.Connection 
= DBCon;
InBlock.gif
InBlock.gif        
// Opening the connection and executing the SQL query. 
InBlock.gif
        DBCon.Open();
InBlock.gif        OrdersReader 
= Command.ExecuteReader(CommandBehavior.CloseConnection);
InBlock.gif
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//*
InBlock.gif        DataTable myTable = new DataTable();
InBlock.gif        myTable.Load(OrdersReader);
ExpandedSubBlockEnd.gif        
*/

InBlock.gif         
InBlock.gif        
// Binding the Data Reader to the GridView control
InBlock.gif
        gvOrders.DataSource = OrdersReader;
InBlock.gif        gvOrders.DataBind();
InBlock.gif
InBlock.gif        
// Closing connection after we are done processing all order records
InBlock.gif
        DBCon.Close();
ExpandedBlockEnd.gif    }

None.gif
None.gif    
protected   void  gvOrders_RowDataBound( object  sender, GridViewRowEventArgs e)
ExpandedBlockStart.gifContractedBlock.gif    
dot.gif {
InBlock.gif        IDataRecord OrderRecord;
InBlock.gif        Label lblOrderDetail;
InBlock.gif
InBlock.gif        
// Retrieving the currently bound record from the Data Reader
InBlock.gif        
// using the IDataRecord interface
InBlock.gif
        OrderRecord = e.Row.DataItem as IDataRecord;
InBlock.gif
InBlock.gif        
// Retrieving reference to the Label Control inside the current 
InBlock.gif        
// GridView row. This Label will be populated with Order Details
InBlock.gif
        lblOrderDetail = e.Row.FindControl("lblOrderDetail"as Label;
InBlock.gif
InBlock.gif        
if ((OrderRecord == null|| (lblOrderDetail == null))
InBlock.gif            
return;
InBlock.gif        
InBlock.gif        SqlCommand Command 
= new SqlCommand();
InBlock.gif        SqlDataReader OrderDetailReader;
InBlock.gif
InBlock.gif        
// Creating an SQL query to retrieve details 
InBlock.gif        
// for the currently processed order
InBlock.gif
        Command.CommandText = 
InBlock.gif                
"SELECT Products.ProductName, [Order Details].UnitPrice, " +
InBlock.gif                
" [Order Details].Quantity, [Order Details].Discount " +
InBlock.gif                
" FROM [Order Details], Products " +
InBlock.gif                
" WHERE [Order Details].ProductID = Products.ProductID " +
InBlock.gif                
" AND [Order Details].OrderID = " +
InBlock.gif                Convert.ToString(OrderRecord[
"OrderID"]);
InBlock.gif
InBlock.gif        Command.CommandType 
= CommandType.Text;
InBlock.gif
InBlock.gif        
// Reusing the same connection object that was used in retrieving 
InBlock.gif        
// allorder records from the Orders table
InBlock.gif
        Command.Connection = DBCon;
InBlock.gif
InBlock.gif        
// Executing SQL query without passing CommandBehavior.CloseConnection 
InBlock.gif        
// as parameter to ExecuteReader. We don't want the connection
InBlock.gif        
// to automatically close because we want to reuse it for more operations
InBlock.gif
        OrderDetailReader = Command.ExecuteReader();
InBlock.gif
InBlock.gif        
while (OrderDetailReader.Read())
ExpandedSubBlockStart.gifContractedSubBlock.gif        
dot.gif{
InBlock.gif            
// Populating the lable control with the product name field
InBlock.gif
            lblOrderDetail.Text += OrderDetailReader[0].ToString() + " " + OrderDetailReader[1].ToString() + "<Br>";
ExpandedSubBlockEnd.gif        }

ExpandedBlockEnd.gif    }

None.gif
</ script >
None.gif
None.gif
< html xmlns = " http://www.w3.org/1999/xhtml "   >
None.gif
< head id = " Head1 "  runat = " server " >
None.gif    
< title > Multiple Active Result Sets </ title >
None.gif
</ head >
None.gif
< body >
None.gif    
< form id = " form1 "  runat = " server " >
None.gif    
< div >
None.gif        
< asp:Label ID = " lblCounter "  Runat = " server " ></ asp:Label >
None.gif        
< br  />
None.gif        
< asp:GridView ID = " gvOrders "  Runat = " server "  AutoGenerateColumns = " False "  
None.gif                OnRowDataBound
= " gvOrders_RowDataBound "  Width = " 100% " >
None.gif            
< Columns >
None.gif        
< asp:BoundField HeaderText = " Company Name "                  
None.gif                DataField
= " CompanyName " ></ asp:BoundField >
None.gif        
< asp:BoundField HeaderText = " Contact Name "  
None.gif                DataField
= " ContactName " ></ asp:BoundField >
None.gif        
< asp:TemplateField >
None.gif        
< HeaderTemplate >
None.gif                Order Detail
None.gif        
</ HeaderTemplate >
None.gif        
< ItemTemplate >
None.gif                
< asp:Label ID = " lblOrderDetail "  runat = " server " ></ asp:Label >
None.gif        
</ ItemTemplate >
None.gif                    
None.gif        
</ asp:TemplateField >
None.gif                
< asp:BoundField HeaderText = " Order Date "  DataField = " orderdate "  
None.gif                        DataFormatString
= " {0:d} " ></ asp:BoundField >
None.gif                
< asp:BoundField HeaderText = " Required Date "  DataField = " requireddate "  
None.gif                        DataFormatString
= " {0:d} " ></ asp:BoundField >
None.gif                
< asp:BoundField HeaderText = " Shipped Date "  DataField = " shippeddate "  
None.gif                        DataFormatString
= " {0:d} " ></ asp:BoundField >
None.gif            
</ Columns >
None.gif        
</ asp:GridView >< br  />
None.gif        
< br  />     
None.gif    
</ div >
None.gif    
</ form >
None.gif
</ body >
None.gif
</ html >
None.gif

 

 

References:

1. Professional ASP.NET 2.0, by Bill Evjen, Scott Hanselman, Farhan Muhammad, Srinivasa Sivakumar, Devin Rader. Wrox - Wiley Publishing Company 2005

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值