Manipulace s daty

Stáhnout ADO.NET

Před zavedením několika sad aktivních výsledků (MARS) museli vývojáři k řešení určitých scénářů použít buď více připojení, nebo kurzory na straně serveru. Kromě toho, když bylo v transakční situaci použito více připojení, vyžadovala se svázaná připojení (s sp_getbindtoken a sp_bindsession). Následující scénáře ukazují, jak místo více připojení používat připojení s podporou MARS.

Použití více příkazů s MARS

Následující konzolová aplikace ukazuje, jak používat dva SqlDataReader objekty se dvěma SqlCommand objekty a jeden SqlConnection objekt s povoleným MARS.

Example

Příklad otevře jedno připojení k databázi AdventureWorks . Pomocí objektu SqlCommand se vytvoří SqlDataReader. Jakmile se použije první SqlDataReader, otevře se druhý SqlDataReader, přičemž jako vstup do klauzule WHERE pro druhý čtecí modul se použijí data z prvního SqlDataReader.

Poznámka:

Následující příklad používá ukázkovou databázi AdventureWorks , která je součástí SQL Serveru. Připojovací řetězec uvedený v ukázkovém kódu předpokládá, že je databáze nainstalovaná a dostupná v místním počítači. Podle potřeby upravte připojovací řetězec pro vaše prostředí.

using System;  
using System.Data;  
using Microsoft.Data.SqlClient;  
  
class Class1  
{  
static void Main()  
{  
  // By default, MARS is disabled when connecting  
  // to a MARS-enabled host.  
  // It must be enabled in the connection string.  
  string connectionString = GetConnectionString();  
  
  int vendorID;  
  SqlDataReader productReader = null;  
  string vendorSQL =   
    "SELECT VendorId, Name FROM Purchasing.Vendor";  
  string productSQL =   
    "SELECT Production.Product.Name FROM Production.Product " +  
    "INNER JOIN Purchasing.ProductVendor " +  
    "ON Production.Product.ProductID = " +   
    "Purchasing.ProductVendor.ProductID " +  
    "WHERE Purchasing.ProductVendor.VendorID = @VendorId";  
  
  using (SqlConnection awConnection =   
    new SqlConnection(connectionString))  
  {  
    SqlCommand vendorCmd = new SqlCommand(vendorSQL, awConnection);  
    SqlCommand productCmd =   
      new SqlCommand(productSQL, awConnection);  
  
    productCmd.Parameters.Add("@VendorId", SqlDbType.Int);  
  
    awConnection.Open();  
    using (SqlDataReader vendorReader = vendorCmd.ExecuteReader())  
    {  
      while (vendorReader.Read())  
      {  
        Console.WriteLine(vendorReader["Name"]);  
  
        vendorID = (int)vendorReader["VendorId"];  
  
        productCmd.Parameters["@VendorId"].Value = vendorID;  
        // The following line of code requires  
        // a MARS-enabled connection.  
        productReader = productCmd.ExecuteReader();  
        using (productReader)  
        {  
          while (productReader.Read())  
          {  
            Console.WriteLine("  " +  
              productReader["Name"].ToString());  
          }  
        }  
      }  
  }  
      Console.WriteLine("Press any key to continue");  
      Console.ReadLine();  
    }  
  }  
  private static string GetConnectionString()  
  {  
    // To avoid storing the connection string in your code,  
    // you can retrieve it from a configuration file.  
    return "Data Source=(local);Integrated Security=SSPI;" +   
      "Initial Catalog=AdventureWorks;MultipleActiveResultSets=True";  
  }  
}  

Čtení a aktualizace dat pomocí MARS

MARS umožňuje používat jedno připojení jak pro operace čtení, tak pro operace jazyka DML (Data Manipulation Language), a to při více než jedné nevyřízené operaci. Tato funkce odstraňuje nutnost, aby aplikace řešila chyby způsobené zaneprázdněným připojením. Kromě toho může MARS nahradit uživatele kurzorů na straně serveru, které obecně spotřebovávají více prostředků. Vzhledem k tomu, že na jednom připojení může fungovat více operací, můžou sdílet stejný kontext transakce, což eliminuje potřebu používat sp_getbindtoken a sp_bindsession systémových uložených procedur.

Example

Následující konzolová aplikace ukazuje, jak používat dva SqlDataReader objekty se třemi SqlCommand objekty a jeden SqlConnection objekt s povoleným MARS. První objekt příkazu načte seznam dodavatelů, jejichž rating je 5. Druhý objekt příkazu používá ID dodavatele poskytnuté v SqlDataReader k načtení druhého SqlDataReader, který obsahuje všechny produkty pro konkrétního dodavatele. Každý záznam o produktu je navštíven druhým SqlDataReader. Provede se výpočet, který určí, co má být nový OnOrderQty . Třetí objekt příkazu se pak použije k aktualizaci tabulky ProductVendor novou hodnotou. Celý tento proces probíhá v rámci jedné transakce, která je na konci vrácena zpět.

Poznámka:

Následující příklad používá ukázkovou databázi AdventureWorks , která je součástí SQL Serveru. Připojovací řetězec uvedený v ukázkovém kódu předpokládá, že je databáze nainstalovaná a dostupná v místním počítači. Podle potřeby upravte připojovací řetězec pro vaše prostředí.

using System;  
using System.Collections.Generic;  
using System.Text;  
using System.Data;  
using Microsoft.Data.SqlClient;  
  
class Program  
{  
static void Main()  
{  
  // By default, MARS is disabled when connecting  
  // to a MARS-enabled host.  
  // It must be enabled in the connection string.  
  string connectionString = GetConnectionString();  
  
  SqlTransaction updateTx = null;  
  SqlCommand vendorCmd = null;  
  SqlCommand prodVendCmd = null;  
  SqlCommand updateCmd = null;  
  
  SqlDataReader prodVendReader = null;  
  
  int vendorID = 0;  
  int productID = 0;  
  int minOrderQty = 0;  
  int maxOrderQty = 0;  
  int onOrderQty = 0;  
  int recordsUpdated = 0;  
  int totalRecordsUpdated = 0;  
  
  string vendorSQL =  
      "SELECT VendorID, Name FROM Purchasing.Vendor " +   
      "WHERE CreditRating = 5";  
  string prodVendSQL =  
      "SELECT ProductID, MaxOrderQty, MinOrderQty, OnOrderQty " +  
      "FROM Purchasing.ProductVendor " +   
      "WHERE VendorID = @VendorID";  
  string updateSQL =  
      "UPDATE Purchasing.ProductVendor " +   
      "SET OnOrderQty = @OrderQty " +  
      "WHERE ProductID = @ProductID AND VendorID = @VendorID";  
  
  using (SqlConnection awConnection =   
    new SqlConnection(connectionString))  
  {  
    awConnection.Open();  
    updateTx = awConnection.BeginTransaction();  
  
    vendorCmd = new SqlCommand(vendorSQL, awConnection);  
    vendorCmd.Transaction = updateTx;  
  
    prodVendCmd = new SqlCommand(prodVendSQL, awConnection);  
    prodVendCmd.Transaction = updateTx;  
    prodVendCmd.Parameters.Add("@VendorId", SqlDbType.Int);  
  
    updateCmd = new SqlCommand(updateSQL, awConnection);  
    updateCmd.Transaction = updateTx;  
    updateCmd.Parameters.Add("@OrderQty", SqlDbType.Int);  
    updateCmd.Parameters.Add("@ProductID", SqlDbType.Int);  
    updateCmd.Parameters.Add("@VendorID", SqlDbType.Int);  
  
    using (SqlDataReader vendorReader = vendorCmd.ExecuteReader())  
    {  
      while (vendorReader.Read())  
      {  
        Console.WriteLine(vendorReader["Name"]);  
  
        vendorID = (int) vendorReader["VendorID"];  
        prodVendCmd.Parameters["@VendorID"].Value = vendorID;  
        prodVendReader = prodVendCmd.ExecuteReader();  
  
        using (prodVendReader)  
        {  
          while (prodVendReader.Read())  
          {  
            productID = (int) prodVendReader["ProductID"];  
  
            if (prodVendReader["OnOrderQty"] == DBNull.Value)  
            {  
              minOrderQty = (int) prodVendReader["MinOrderQty"];  
              onOrderQty = minOrderQty;  
            }  
            else  
            {  
              maxOrderQty = (int) prodVendReader["MaxOrderQty"];  
              onOrderQty = (int)(maxOrderQty / 2);  
            }  
  
            updateCmd.Parameters["@OrderQty"].Value = onOrderQty;  
            updateCmd.Parameters["@ProductID"].Value = productID;  
            updateCmd.Parameters["@VendorID"].Value = vendorID;  
  
            recordsUpdated = updateCmd.ExecuteNonQuery();  
            totalRecordsUpdated += recordsUpdated;  
          }  
        }  
      }  
    }  
    Console.WriteLine("Total Records Updated: " +   
      totalRecordsUpdated.ToString());  
    updateTx.Rollback();  
    Console.WriteLine("Transaction Rolled Back");  
  }  
  
  Console.WriteLine("Press any key to continue");  
  Console.ReadLine();  
}  
private static string GetConnectionString()  
{  
  // To avoid storing the connection string in your code,  
  // you can retrieve it from a configuration file.  
  return "Data Source=(local);Integrated Security=SSPI;" +   
    "Initial Catalog=AdventureWorks;" +   
    "MultipleActiveResultSets=True";  
  }  
}