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. È pertanto possibile combinare codice LINQ to SQL con le applicazioni ADO.NET esistenti ed eseguire la migrazione delle soluzioni ADO.NET correnti a LINQ to SQL. Nell'illustrazione seguente viene fornita una panoramica della relazione.
Connessioni
Quando si crea un oggetto LINQ to SQLDataContext, è possibile specificare una connessione ADO.NET esistente. Per tutte le operazioni relative a DataContext, incluse le query, verrà utilizzata la connessione specificata. Se la connessione è già aperta, al termine della sessione verrà lasciata da LINQ to SQL nello stato in cui si trova.
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()
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();
È comunque possibile accedere alla connessione e chiuderla utilizzando 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 utilizzato anche DataContext.
Il metodo preferito per creare transazioni con .NET Framework consiste nell'utilizzare l'oggetto TransactionScope. Utilizzando questo approccio, è possibile creare transazioni distribuite che potranno essere utilizzate 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 ts As New TransactionScope()
db.SubmitChanges()
ts.Complete()
End Using
using (TransactionScope ts = new TransactionScope())
{
db.SubmitChanges();
ts.Complete();
}
Non è possibile utilizzare questo approccio per tutti i database. Ad esempio, la connessione di SqlClient non consente di promuovere transazioni di sistema quando viene utilizzata con un server SQL Server 2000. Al contrario, viene inserita automaticamente in una transazione distribuita completa quando viene rilevato l'utilizzo 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 utilizzare 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:
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")
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"
);
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:
Dim results As IEnumerable(Of Customer) = _
db.ExecuteQuery(Of Customer)( _
"SELECT contactname FROM customers WHERE city = {0}, 'London'")
End Sub
IEnumerable<Customer> results = db.ExecuteQuery<Customer>(
"select contactname from customers where city = {0}",
"London"
);
Nota |
---|
I parametri sono espressi nel testo della query utilizzando la stessa notazione con parentesi graffe utilizzata 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). |
Vedere anche
Attività
Procedura: riutilizzare una connessione tra un comando ADO.NET e DataContext (LINQ to SQL)