Поделиться через


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 and ADO.NET

Связи

При создании 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, его можно добавить в собственную транзакцию базы данных.

Предпочтительный способ выполнения транзакций с платформа .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 осуществлять запросы или отправлять изменения будет недостаточной для выполнения специализированной задачи. В подобных случаях, чтобы запустить команды SQL в базе данных и преобразовать результаты запроса в объекты, можно использовать метод ExecuteQuery.

Например, предположим, что данные для класса 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).

См. также