Часто задаваемые вопросы о 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) и посмотрим, как делаются операции фиксации в памяти и физической фиксации.