ADO.NET 和 LINQ to SQL
LINQ to SQL 是 ADO.NET 系列技术的一部分, 以 ADO.NET 提供程序模型提供的服务为基础。 因此,你可以将 LINQ to SQL 代码与现有的 ADO.NET 应用程序混合在一起,并将当前 ADO.NET 解决方案迁移到 LINQ to SQL。 下图高度概括了这种关系。
连接
你可以在创建 LINQ to SQL DataContext 时提供现有的 ADO.NET 连接。 对 DataContext 的所有操作(包括查询)都使用所提供的这个连接。 如果你已经打开此连接,则在你使用完此连接时,LINQ to SQL 会保持其打开状态不变。
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()
你始终可以访问此连接,并可以使用 Connection 属性自行关闭它,如下面的代码所示:
db.Connection.Close();
db.Connection.Close()
事务
当你的应用程序已经启动了你自己的数据库事务并且你希望你的 DataContext 包含在内时,你可以向你的 DataContext 提供此事务。
通过 .NET Framework 处理事务的首选方法是使用 TransactionScope 对象。 通过使用此方法,你可以创建跨数据库及其他驻留在内存中的资源管理器执行的分布式事务。 事务范围几乎不需要资源就可以启动。 它们仅在事务范围内存在多个连接时才将自身提升为分布式事务。
using (TransactionScope ts = new TransactionScope())
{
db.SubmitChanges();
ts.Complete();
}
Using ts As New TransactionScope()
db.SubmitChanges()
ts.Complete()
End Using
不能将此方法用于所有数据库。 例如,SqlClient 连接如果对 SQL Server 2000 服务器有效,则无法提升系统事务。 它采取的方法是,只要它发现有使用事务范围的情况,它就会自动向完整的分布式事务登记。
直接 SQL 命令
有时您可能会遇到这样的情况:DataContext 查询或提交更改的能力不足以满足您需要执行的专门任务的需要。 在这些情况下,你可以使用 ExecuteQuery 方法向数据库发出 SQL 命令,将查询结果转换成对象。
例如,假定 Customer
类的数据分布在两个表(customer1 和 customer2)中。 下面的查询将返回 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")
只要表格结果中的列名与你的实体类的列属性匹配,LINQ to SQL 就会为你创建不在任何 SQL 查询范围之内的对象。
参数
ExecuteQuery 方法接受参数。 下面的代码执行参数化查询:
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
备注
在查询文本中使用 Console.WriteLine()
和 String.Format()
所用的大括号表示法来表示参数。 String.Format()
获取您提供的查询字符串,然后将括在大括号内的参数替换为所生成的参数名,如 @p0
、@p1
…… @p(n)
。