Последние несколько месяцев моей работы способствовали активному исследованию технологии LinqToSql. Поэтому хочу рассказать о моем опыте, это будет серия небольших заметок которые возможно помогут кому-то быстрее и глубже вникнуть в суть новой концепции доступа к данным, разработанной компанией Microsoft.
Самый простой способ воспользоваться объектным доступом к данным — это создать dbml-модель БД. Но бывают ситуации, когда производительность является ключевым фактором и получить данные с SQL Server-а можно исключительно хранимой процедурой. В этом случае мы, конечно, можем воспользоваться дизайнером Visual Studio. Но, к сожалению, его функции по конфигурированию параметров вызова хранимых процедур очень ограничены. Меня очень раздражало то, что я не имею возможность руками проставить тип передаваемого параметра.
Берем хранимую процедуру:
Дизайнер не позволяет изменить тип параметра с XElement на string.
Что делаем?
Объявляем класс наследник волшебного DataContext:
Объявляем прототип результата:
Использование 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И прописываем непосредственно Proxy-метод для вызова процедуры:
2: {
3: public long Id { get; set; }
4: public string Name { get; set; }
5: public string Description { get; set; }
6: }
7:
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»)]Таким образом, можно полностью реализовать доступ к БД на технологии LinqToSql (без использования ADO.NET).
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: