ADO.NET und LINQ to SQL
LINQ to SQL gehört zur ADO.NET Technologiefamilie. Es basiert auf den vom ADO.NET-Anbietermodell bereitgestellten Diensten. Sie können daher LINQ to SQL-Code mit vorhandenen ADO.NET-Anwendungen mischen und aktuelle ADO.NET-Lösungen zu LINQ to SQL migrieren. Die folgende Abbildung stellt eine allgemeine Ansicht der Beziehung dar.
Verbindungen
Sie können eine vorhandene ADO.NET-Verbindung bereitstellen, wenn Sie in LINQ to SQL einen DataContexterstellen. Alle Vorgänge mit dem DataContext (einschließlich Abfragen) verwenden diese bereitgestellte Verbindung. Ist die Verbindung bereits geöffnet, verändert LINQ to SQL sie nach deren Verwendung nicht.
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()
Sie können stets auf die Verbindung zugreifen und diese selbst beenden, indem Sie die Connection-Eigenschaft wie im folgenden Code verwenden:
db.Connection.Close();
db.Connection.Close()
Transaktionen
Sie können Ihren DataContext mit Ihrer eigenen Datenbanktransaktion ergänzen, wenn Ihre Anwendung die Transaktion bereits initiiert hat und Sie möchten, dass der DataContext berücksichtigt wird.
Die bevorzugte Methode für Transaktionen mit .NET Framework ist die Verwendung des TransactionScope-Objekts. Mithilfe dieses Ansatzes können Sie verteilte Transaktionen erstellen, die über Datenbanken hinweg und in Verbindung mit anderen speicherresidenten Ressourcen-Managern funktionieren. Transaktionsbereiche erfordern zunächst wenige Ressourcen. Sie stufen sich selbst nur dann zu verteilten Transaktionen hoch, wenn mehrere Verbindungen innerhalb des Transaktionsbereichs vorliegen.
using (TransactionScope ts = new TransactionScope())
{
db.SubmitChanges();
ts.Complete();
}
Using ts As New TransactionScope()
db.SubmitChanges()
ts.Complete()
End Using
Sie können diesen Ansatz nicht für alle Datenbanken verwenden. Beispielsweise kann die SqlClient-Verbindung keine Systemtransaktionen hochstufen, wenn ein Server mit SQL Server 2000 verwendet wird. Stattdessen wird automatisch eine vollständige, verteilte Transaktion erzeugt, wenn erkannt wird, dass ein Transaktionsbereich genutzt wird.
Direkte SQL-Befehle
Es kann zu Situationen kommen, in denen die Möglichkeiten des DataContext zum Abfragen oder zum Übergeben von Änderungen für die spezifische Aufgabe nicht ausreichen. In diesen Fällen können Sie die ExecuteQuery-Methode verwenden, um SQL-Befehle an die Datenbank zu übergeben und die Abfrageergebnisse in Objekte zu konvertieren.
Nehmen Sie zum Beispiel an, dass die Daten der Customer
-Klasse auf zwei Tabellen (customer1 und customer2) verteilt sind. Die folgende Abfrage gibt eine Sequenz von Customer
-Objekten zurück:
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")
Solange die Spaltennamen in tabellarischen Ergebnissen den Spalteneigenschaften Ihrer Entitätsklasse entsprechen, erzeugt LINQ to SQL Ihre Objekte aus einer beliebigen SQL-Abfrage.
Parameter
Die ExecuteQuery-Methode akzeptiert Parameter. Der folgende Code führt eine parametrisierte Abfrage aus:
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
Hinweis
Parameter werden im Abfragetext mithilfe der gleichen verschachtelten Schreibweise wie in Console.WriteLine()
und String.Format()
ausgedrückt. String.Format()
ersetzt die verschachtelten Parameter der angegebenen Abfragezeichenfolge durch generierte Parameternamen, wie z. B. @p0
, @p1
…, @p(n)
.