Виклик функцій баз даних в Linq to Entities

Доброго вечора Smile. В даній статті я хочу показати вам простий спосіб виклику функцій баз даних у виразах Linq to Entities.

Для тих, хто забув як виглядає такий запит, перегляньте наступний приклад:

1 static void Main(string[] args) 2 { 3 SampleDBEntities db = new SampleDBEntities(); 4 5 var customersQuery = from customer in db.Customers 6 where customer.Age > 18 7 select customer; 8 } 9

В даному випадку, я просто створюю екземпляр класу, який був згенерований за допомогою Entity Framework та роблю Linq запит до колекції Customers, вибираючи ті сутності, які мають вік більше 18 років.

Потрібно зробити акцент на тому, що даний запит буде інтерпретовано в запит специфічний до бази даних (мова SQL). Коли ми викличемо якийсь метод, наприклад ToList, то цей запит полетить на базу даних і буде там виконаний:

1 2 List<Customer> retrievedCustomers = customersQuery.ToLis(); 3

Писати такі запити дуже просто і зручно, але час від часу має виникнути не зовсім очевидна задача.

Для прикладу, уявіть, що в вас в базі даних дата зберігається в текстовому форматі, і вам потрібно її перетворити в дату, і зробити певну вибірку. Наприклад, вам потрібно зробити схожий запит на Linq:

1 SELECT * FROM Customers 2 WHERE convert(datetime, BirthDate) > convert(datetime,'10,23,2016'). 3

Цей підхід реалізувати досить легко Smile. Є ось такий клас SqlFunctions, який дозволяє викликати певний набір стандартних функцій в запитах Linq, які в кінцевому результаті будуть інтерпретовані на функції бази даних:

1 var query = from customer in db.Customers 2 where customer.Age > 20 && SqlFunctions.IsDate(customer.BirthDate) == 1 3 select customer; 4

У випадку, якщо клас SqlFunctions не має необхідного методу, ви можете вручну відобразити метод будь-якого класу на функцію бази даних.

Даний приклад не був протестований і його виконання не гарантується, тому, перевірте типи вхідних і вихідних параметрів функції перед його реалізацією.

Потрібно відкрити файл, який був згенерований за допомогою Entity Framework у XML редакторі, знайти кінець секції <edmx:StorageModels> та добавити ось такий елемент:

1 <Function Name="convert" ReturnType="datetime" IsComposable="true" Aggregate="false" BuiltIn="true"> 2 <Parameter Name="datatype" Mode="In" Type="char"/> 3 <Parameter Name="format" Mode="In" Type="char"/> 4 </Function> 5

Створіть статичний клас та назвіть його DatabaseFunctions:

1 public static class DatabaseFunctions 2 { 3 [EdmFunction("SampleDBModel.Store", "convert")] 4 public static DateTime? convert(string datatype, string format) 5 { 6 throw new NotSupportedException(); 7 } 8 } 9

Цей метод не має містити ніякої реалізації і має бути поміченим атрибутом EdmFunctionAttribute, в який ми передаємо назву простору імен, яку можна отримати з елемента Schema, який знаходиться на початку XML файлу, який описує згенеровані сутності:

1 <Schema Namespace="SampleDBModel.Store" Alias="Self" Provider="System.Data.SqlServerCe.3.5" ProviderManifestToken="3.5"

Також, потрібно передати назву функції, яку ми хочемо викликати, в нашому випадку – convert.

Тепер, все що залишилось це викликати цю функцію у виразі Linq:

1 var query = from customer in db.Customers 2 where DatabaseFunctions.convert("datetime", customer.BirthDate) < new DateTime(2000, 03, 15) 3 select customer; 4

Ось таким чином, можна досить просто викликати будь-яку функцію в запиті Linq, яка знаходиться в базі даних Smile.

 

Скачати код

Advertisements

, , ,

  1. Leave a comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: