ADO.NET 与 LINQ to SQL

更新:November 2007

LINQ to SQL 是 ADO.NET 系列技术的一部分。它基于由 ADO.NET 提供程序模型提供的服务。因此,您可以将 LINQ to SQL 代码与现有的 ADO.NET 应用程序混合在一起,将当前 ADO.NET 解决方案迁移到 LINQ to SQL。下图高度概括了这种关系。

LINQ to SQL 以及 ADO.NET

连接

在创建 LINQ to SQL DataContext 时,可以提供现有 ADO.NET 连接。对 DataContext 的所有操作(包括查询)都使用所提供的这个连接。如果此连接已经打开,则在您使用完此连接时,LINQ to SQL 会保持它的打开状态不变。

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();

您始终可以访问此连接,并可以使用 Connection 属性自行关闭它,如下面的代码所示:

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

事务

当您的应用程序已经启动了您自己的数据库事务并且您希望您的 DataContext 包含在内时,您可以向您的 DataContext 提供此事务。

通过 .NET Framework 创建事务的首选方法是使用 TransactionScope 对象。通过使用此方法,您可以创建跨数据库及其他驻留在内存中的资源管理器执行的分布式事务。事务范围几乎不需要资源就可以启动。它们仅在事务范围内存在多个连接时才将自身提升为分布式事务。

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

不能将此方法用于所有数据库。例如,SqlClient 连接在针对 SQL Server 2000 服务器使用时无法提升系统事务。它采取的方法是,只要它发现有使用事务范围的情况,它就会自动向完整的分布式事务登记。

直接 SQL 命令

有时您可能会遇到这样的情况:DataContext 查询或提交更改的能力不足以满足您需要执行的专门任务的需要。在这些情况下,您可以使用 ExecuteQuery 方法向数据库发出 SQL 命令,将查询结果转换成对象。

例如,假定 Customer 类的数据分布在两个表(customer1 和 customer2)中。下面的查询将返回 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"
);

只要表格结果中的列名与您的实体类的列属性匹配,LINQ to SQL 就会为您创建不在任何 SQL 查询范围之内的对象。

参数

ExecuteQuery 方法接受参数。下面的代码执行参数化查询:

    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"
);
说明:

在查询文本中使用 Console.WriteLine() 和 String.Format() 所用的大括号表示法来表示参数。String.Format() 获取您提供的查询字符串,然后将括在大括号内的参数替换为所生成的参数名,如 @p0、@p1 … @p(n)。

请参见

任务

如何:重用 ADO.NET 命令和 DataContext 之间的连接 (LINQ to SQL)

其他资源

背景信息 (LINQ to SQL)