• Microsoft .NET
  • LINQ
  • Часто задаваемые вопросы о LINQ - часть вторая

Часто задаваемые вопросы о LINQ - часть вторая - Как выполняются хранимые процедуры с помощью LINQ

ОГЛАВЛЕНИЕ

Как выполняются хранимые процедуры с помощью LINQ

Шаг 1: Создать хранимую процедуру

Ниже приведена хранимая процедура, используемая для выращивания объектов LINQ.

Create PROCEDURE dbo.usp_SelectCustomer
AS
Select CustomerId,CustomerCode,CustomerName from Customer
RETURN

Шаг 2: Создать сущность LINQ

Вышеуказанная хранимая процедура возвращает ‘CustomerId’,’CustomerCode’ и ‘CustomerName’, поэтому надо приготовить сущность LINQ согласно данным, возвращаемым хранимой процедурой. Если вы не знакомы с сущностями LINQ, прочитайте основы в OneManyandOneOneLINQ.aspx

[Table(Name = "Customer")]
public class clsCustomerEntity
{
private int _CustomerId;
private string _CustomerCode;
private string _CustomerName;

[Column(DbType = "nvarchar(50)")]
public string CustomerCode
{
set
{
_CustomerCode = value;
}
get
{
return _CustomerCode;
}
}

[Column(DbType = "nvarchar(50)")]
public string CustomerName
{
set
{
_CustomerName = value;
}
get
{
return _CustomerName;
}
}

[Column(DbType = "int", IsPrimaryKey = true)]
public int CustomerId
{
set
{
_CustomerId = value;
}
get
{
return _CustomerId;
}
}
}

Шаг 3: Унаследовать от класса DataContext

Для выполнения хранимых процедур LINQ предоставляет функцию вызова ‘ExecuteMethod’, принадлежащую классу ‘DataContext’. Эта функция возвращает ‘ISingleresult’ коллекции сущностей. Функция вызова ‘ExecuteMethod’ – защищенная функция и вызывается только через наследование. Методы и функции, из которых вызываются хранимые процедуры, формируют DAL. То есть ‘ExecuteMethod’ должен входить в DAL.

Как сказано, функция чисто защищенная, вызываемая только путем наследования, а не агрегирования. Неясно, почему Microsoft принуждает к этому, поэтому надо создать еще один лишний класс, наследуемый от ‘DataContext’, а затем вставить соответствующие вызовы функции для хранимых процедур. Ниже приведен фрагмент кода, в котором наследуется от класса ‘DataContext’ и создается новый класс DAL по имени ‘ClsMyContext’.

public class clsMyContext : DataContext
{}

Шаг 4: Приписать с помощью атрибута Функция

Была создана функция ‘GetCustomerAll’, приписанная с помощью атрибута ‘Function’ из пространства имен ‘System.Data.Linq.Mapping’. Атрибут ‘Function’ имеет параметр имя, задающий имя хранимой процедуры; сейчас хранимая процедура - ‘usp_SelectCustomer’, как определено в предыдущих шагах.

Параметр ‘IsComposable’ определяет, предназначен ли этот вызов метода (для или) для UDF, т.е. определённой пользователем функции. Если ‘IsComposable’ равен false, то это хранимая процедура, а если равен true, то это определённая пользователем функция.

[Function(Name = "usp_SelectCustomer", IsComposable = false)]

public ISingleResult<clsCustomerEntity> getCustomerAll()
{
}

Шаг 5: Вызвать вызов Executemethod

Пора заполнить пустую функцию ‘GetCustomerAll’. Ниже приведен фрагмент кода, выполняющий вызов ‘ExecuteMethod’. Этот вызов возвращает объект ‘IExecuteResult’.

IExecuteResult objResult = this.ExecuteMethodCall(this,(MethodInfo)(MethodInfo.GetCurrentMethod()));

Объект, возвращенный из ‘IExecuteResult’, имеет свойство ‘ReturnValue’, из которого можно получить коллекцию результатов типа ‘ClsCustomerEntity’.

ISingleResult<clsCustomerEntity> objresults = (ISingleResult<clsCustomerEntity>) objResult.ReturnValue;

Ниже приведен полный фрагмент кода с функцией.

[Function(Name = "usp_SelectCustomer", IsComposable = false)]
public ISingleResult<clsCustomerEntity> getCustomerAll()
{
IExecuteResult objResult = this.ExecuteMethodCall(this,(MethodInfo)(MethodInfo.GetCurrentMethod()));

ISingleResult<clsCustomerEntity> objresults = (ISingleResult<clsCustomerEntity>) objResult.ReturnValue;
return objresults;
}

Шаг 6: Вызвать контекст данных в клиенте

На последнем шаге создается объект контекста, вызывается функция, и коллекция объектов обходится в цикле с выводом данных на экран.

clsMyContext objContext = new clsMyContext(strConnectionString);
foreach(var row in objContext.getCustomerAll())
{
Response.Write(row.CustomerCode);
}

Объясните фиксацию в памяти и физическую фиксацию LINQ

Объекты-сущности образуют основу технологий LINQ. Поэтому при отправке любых данных в базу данных они проходят через объекты LINQ. Операции базы данных делаются посредством класса ‘DataContext’. Как сказано выше, сущности образуют основу LINQ, поэтому все данные сначала отправляются этим сущностям и затем направляются в реальную физическую базу данных. Из-за этого фиксация транзакции базы данных является двухэтапным процессом: первый этап происходит в памяти, а второй этап – физическая фиксация.

Для выполнения операции в памяти ‘DataContext’ предоставляет методы ‘DeleteOnSubmit’ и ‘InsertOnSubmit’. Когда эти методы вызываются из класса ‘DataContext’, они добавляют и обновляют данные в памяти объектов-сущностей. Учтите, что эти методы не меняют / не добавляют новые данные в реальную базу данных.

После завершения операций в памяти вызывается метод ‘SubmitChanges()’ для отправки всех обновлений в базу данных. Этот метод фиксирует данные в физической базе данных.

Рассмотрим таблицу пользователей (customerid, customercode и customername) и посмотрим, как делаются операции фиксации в памяти и физической фиксации.