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 и 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, если приложение уже инициировало ее и вы хотите включить в неё 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).

См. также