Condividi tramite


ADO.NET e LINQ to SQL

LINQ to SQL fa parte della famiglia di tecnologie ADO.NET. e si basa sui servizi forniti dal modello provider ADO.NET. È quindi possibile combinare codice LINQ to SQL con le applicazioni di ADO.NET esistenti ed eseguire la migrazione delle soluzioni di ADO.NET correnti a LINQ to SQL. Nell'illustrazione seguente viene fornita una panoramica della relazione.

LINQ to SQL and ADO.NET

Connessioni

È possibile fornire una connessione ADO.NET esistente quando si crea un DataContext LINQ to SQL. Per tutte le operazioni relative a DataContext, incluse le query, verrà usata la connessione specificata. Se la connessione è già aperta, LINQ to SQL la lascia invariata al termine dell'operazione.

string connString = @"Data Source=.\SQLEXPRESS;AttachDbFilename=c:\northwind.mdf;
    Integrated Security=True; Connect Timeout=30; User Instance=True";
SqlConnection nwindConn = new SqlConnection(connString);
nwindConn.Open();

Northwnd interop_db = new Northwnd(nwindConn);

SqlTransaction nwindTxn = nwindConn.BeginTransaction();

try
{
    SqlCommand cmd = new SqlCommand(
        "UPDATE Products SET QuantityPerUnit = 'single item' WHERE ProductID = 3");
    cmd.Connection = nwindConn;
    cmd.Transaction = nwindTxn;
    cmd.ExecuteNonQuery();

    interop_db.Transaction = nwindTxn;

    Product prod1 = interop_db.Products
        .First(p => p.ProductID == 4);
    Product prod2 = interop_db.Products
        .First(p => p.ProductID == 5);
    prod1.UnitsInStock -= 3;
    prod2.UnitsInStock -= 5;

    interop_db.SubmitChanges();

    nwindTxn.Commit();
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
    Console.WriteLine("Error submitting changes... all changes rolled back.");
}

nwindConn.Close();
Dim conString = "Data Source=.\SQLEXPRESS;AttachDbFilename=c:\northwind.mdf; Integrated Security=True;Connect Timeout=30;User Instance=True"
Dim northwindCon = New SqlConnection(conString)
northwindCon.Open()

Dim db = New Northwnd("...")
Dim northwindTransaction = northwindCon.BeginTransaction()

Try
    Dim cmd = New SqlCommand( _
            "UPDATE Products SET QuantityPerUnit = 'single item' " & _
            "WHERE ProductID = 3")
    cmd.Connection = northwindCon
    cmd.Transaction = northwindTransaction
    cmd.ExecuteNonQuery()

    db.Transaction = northwindTransaction

    Dim prod1 = (From prod In db.Products _
                 Where prod.ProductID = 4).First
    Dim prod2 = (From prod In db.Products _
                 Where prod.ProductID = 5).First
    prod1.UnitsInStock -= 3
    prod2.UnitsInStock -= 5

    db.SubmitChanges()

    northwindTransaction.Commit()

Catch e As Exception

    Console.WriteLine(e.Message)
    Console.WriteLine("Error submitting changes... " & _
"all changes rolled back.")
End Try

northwindCon.Close()

È comunque possibile accedere alla connessione e chiuderla usando la proprietà Connection, come nel codice seguente:

db.Connection.Close();
db.Connection.Close()

Transazioni

È possibile fornire l'oggetto DataContext con la transazione di database personalizzata qualora l'applicazione abbia già avviato la transazione e si desideri che venga usato anche DataContext.

Il metodo preferito per creare transazioni con .NET Framework consiste nell'usare l'oggetto TransactionScope. Usando questo approccio, è possibile creare transazioni distribuite che potranno essere usate sia con database che con altri gestori di risorse residenti in memoria. Gli ambiti della transazione possono essere avviati con risorse limitate. Vengono promossi a transazioni distribuite quando all'interno dell'ambito della transazione sono attive più connessioni.

using (TransactionScope ts = new TransactionScope())
{
    db.SubmitChanges();
    ts.Complete();
}
Using ts As New TransactionScope()
    db.SubmitChanges()
    ts.Complete()
End Using

Non è possibile usare questo approccio per tutti i database. Ad esempio, la connessione di SqlClient non consente di promuovere transazioni di sistema quando viene usata con un server SQL Server 2000. Al contrario, viene inserita automaticamente in una transazione distribuita completa quando viene rilevato l'uso di un ambito della transazione.

Comandi SQL diretti

In alcune situazioni la capacità di DataContext di eseguire query o inviare modifiche è insufficiente per l'attività specifica che si desidera eseguire. In queste circostanze è possibile usare il metodo ExecuteQuery per inviare comandi SQL al database e convertire i risultati della query in oggetti.

Ad esempio, si supponga che i dati per la classe Customer siano distribuiti in due tabelle (customer1 e customer2). La query seguente consente di restituire una sequenza di oggetti Customer:

            IEnumerable<Customer> results = db.ExecuteQuery<Customer>(
    @"select c1.custid as CustomerID, c2.custName as ContactName
        from customer1 as c1, customer2 as c2
        where c1.custid = c2.custid"
);
    Dim results As IEnumerable(Of Customer) = _
db.ExecuteQuery(Of Customer)( _
"SELECT [c1].custID as CustomerID," & _
    "[c2].custName as ContactName" & _
    "FROM customer1 AS [c1], customer2 as [c2]" & _
    "WHERE [c1].custid = [c2].custid")

A condizione che i nomi di colonna nei risultati tabulari corrispondano alle proprietà di colonna della classe di entità, in LINQ to SQL verranno creati oggetti da qualsiasi query SQL.

Parametri

Il metodo ExecuteQuery accetta l'uso di parametri. Nel codice seguente viene eseguita una query con parametri:

            IEnumerable<Customer> results = db.ExecuteQuery<Customer>(
    "select contactname from customers where city = {0}",
    "London"
);
    Dim results As IEnumerable(Of Customer) = _
db.ExecuteQuery(Of Customer)( _
    "SELECT contactname FROM customers WHERE city = {0}, 'London'")
End Sub

Nota

I parametri sono espressi nel testo della query usando la stessa notazione con parentesi graffe usata da Console.WriteLine() e String.Format(). String.Format() sostituisce quindi i parametri con parentesi graffe presenti nella stringa fornita con nomi di parametro generati, ad esempio @p0, @p1 …, @p(n).

Vedi anche