Pull to refresh

Практика использования LinqToSql: Использование Linq для автоматизации вызовов хранимых процедур.

Reading time 3 min
Views 4.3K
Последние несколько месяцев моей работы способствовали активному исследованию технологии LinqToSql. Поэтому хочу рассказать о моем опыте, это будет серия небольших заметок которые возможно помогут кому-то быстрее и глубже вникнуть в суть новой концепции доступа к данным, разработанной компанией Microsoft.

Использование Linq для автоматизации вызовов хранимых процедур.


Самый простой способ воспользоваться объектным доступом к данным — это создать dbml-модель БД. Но бывают ситуации, когда производительность является ключевым фактором и получить данные с SQL Server-а можно исключительно хранимой процедурой. В этом случае мы, конечно, можем воспользоваться дизайнером Visual Studio. Но, к сожалению, его функции по конфигурированию параметров вызова хранимых процедур очень ограничены. Меня очень раздражало то, что я не имею возможность руками проставить тип передаваемого параметра.
Берем хранимую процедуру:
  1: create procedure sp_getItems(
  2: 
  3:  query xml — <query><id>12</id><id>13</id></query>
  4: 
  5: )as
  6: 
  7: begin
  8: 
  9:  select [Id], [Name], [Description]
 10: 
 11:  from [Item] it
 12: 
 13:  inner join (select t.c.value('.', bigint) [requestedid] from query.nodes('query/id') t(c)) as query on query.requestedid = it.[id];
 14: 
 15: end;

Перетащив ее в дизайнере на диаграмму, мы получаем такой прототип:
  1: public System.Data.Linq.ISingleResultsp_getItems(System.Xml.Linq.XElement query){ … }

Дизайнер не позволяет изменить тип параметра с XElement на string.
Что делаем?
Объявляем класс наследник волшебного DataContext:
  1: public class CatalogReader: DataContext
  2: 
  {
  3: 
    public CatalogReader(): base(System.Configuration.ConfigurationManager.ConnectionStrings[«ConnectionString»].ConnectionString)
  4: 
{ }
  5: 
}
  6: 



Объявляем прототип результата:
  1: class Item
  2: 
{
  3: 
  public long Id { get; set; }
  4: 
  public string Name { get; set; }
  5: 
  public string Description { get; set; }
  6: 
}
  7: 

И прописываем непосредственно Proxy-метод для вызова процедуры:
  1: [Function(Name=«sp_getItems»)]
  2: 
public ISingleResult<Item> GetItems([Parameter(DbType=«xml»)] string query)
  3: 
{
  4: 
  var result = base.ExecuteMethodCall(this, (System.Reflection.MethodInfo)System.Reflection.MethodInfo.GetCurrentMethod(), query);
  5: 
  return (ISingleResult<Item>)result.ReturnValue;
  6: 
}
  7: 

Как этим пользоваться:
  1: using (CatalogReader context = new CatalogReader())
  2: 
  return context.GetItems("<query><id>12</id><id>13</id></query>");
  3: 

Output-параметры:

Для того чтобы получить данные из хранимой процедуры, возвращаемые через параметры меняем proxy-функцию
  1: [Function(Name=«sp_getItems»)]
  2: 
public ISingleResult<Item> GetItems([Parameter(DbType=«xml»)] string query, [Parameter(DbType=«int output»)] ref int count)
  3: 
{
  4: 
  var result = base.ExecuteMethodCall(this, (System.Reflection.MethodInfo)System.Reflection.MethodInfo.GetCurrentMethod(), query);
  5: 
  count = (int)result.GetParameterValue(1);
  6: 
  return (ISingleResult<Item>)result.ReturnValue;
  7: 
}
  8: 

Таким образом, можно полностью реализовать доступ к БД на технологии LinqToSql (без использования ADO.NET).
Tags:
Hubs:
+27
Comments 18
Comments Comments 18

Articles