Модель Представлення є з одного боку абстракцією Представлення, а з іншого надає обгортку даних з Моделі, які підлягають скріпленню. Тобто вона містить Модель, яка перетворена до Представленню, а також містить у собі команди, якими може користуватися представлення, щоб впливати на Модель [1, 3].
Надання студентам навичків використання ORM технології дасть їм можливість використовувати шаблони проектування при створены архітектури розроблювального програмного забезпечення які базуються на технології ORM .
Отже, використання ORM в проекті позбавляє розробника від необхідності роботи з SQL і написання великої кількості коду, часто одноманітного і схильного помилок.
Весь генерований ORM код добре перевірений і оптимізований, тому не потрібно в цілому замислюється про його тестуванні. Це безсумнівно є плюсом, але в теж час не варто забувати і про мінуси. Основний з них - це втрата продуктивності через те, що більшість ORM призначені для обробки широкого спектру сценаріїв використання даних, набагато більшого, ніж будь-яке окреме програмне забезпечення зможе використати.
На етапі виконання першого розділу було вирішено наступні задачі:
Досліджено сутність проблеми парадигми «невідповідності», яку вирішує ORM;
Виконано аналіз існуючі архітектурні шаблони проектування, які полегшують і підвищують якість супроводу програмного забезпечення та за рахунок яких проводиться уніфікація термінології, назв модулів і елементів проекту.
Доведено доцільність розробки засобу візуалізації технології LINQ to SQL для його використання в навчальному процесі з метою надання студентам знань та навичок використання ORM-технологій при створенні архітектури розроблювального ПЗ
РОЗДІЛ 2. LINQ to SQL ЯК СУЧАСНА ORM
ПЛАТФОРМА .NET FRAMEWORK
.1 Основні характеристики LINQ to
SQL
У сучасному світі, де панують об'єктно-орієнтовані мови програмування, існує невідповідність між мовою програмування і реляційною базою даних. При написанні програми ми моделюємо класи як представлення об'єктів реального світу. Нам потрібен спосіб збереження цих об'єктів, щоб при перезапуску програми всі ці об'єкти з їх даними не були втрачені.
Однак більшість баз даних промислового масштабу залишаються реляційними і зберігають свою інформацію у вигляді записів в таблицях, а не у вигляді об'єктів. Користувальницький клас може містити кілька адрес і номерів телефонів, що зберігаються в колекціях, які є дочірніми властивостями класу замовника, при збереженні така інформація, швидше за все, розподілиться по багатьом таблицям, наприклад, в таблицю замовників, таблицю адрес і таблицю телефонів. Типи даних,
підтримувані мовою застосування, відрізняються від типів бази даних.
Розробникам доводиться писати власний код, який завантажує і зберігає об'єкти замовників з відповідних таблиць, обробляючи необхідні перетворення даних між мовою додатків і базою даних. Це виснажливий, і часто схильний до помилок процес.
Наявність згаданих проблем
об'єктно-реляційного відображення, часто званих об'єктно-реляційною втратою
відповідності, протягом ряду років призвело до появи широкого розмаїття готових
програмних ORM-рішень. LINQ to SQL - це реалізація ORM початкового рівня від
Microsoft на основі LINQ, призначена для роботи з SQL Server.це запит
інтегрований в мову програмування який дозволяє писати безпечні структуровані
запити до локальних колекціях об’єктів та віддалених джерел даних. з'явився в
NET Framework версии 3.5, який значно розширює можливості синтаксису мов C # і
Visual Basic. LINQ надає стандартні, прості у вивченні шаблони для запиту і
зміни даних і технології, які можуть бути розширені для підтримки практично
будь-якого типу джерела даних. До складу Visual Studio входять збірки ресурсів
LINQ, які зображені на рисунку 2.1, для використання LINQ з колекціями .NET
Framework, базами даних SQL Server, наборами даних ADO.NET і XML-документами.
Рис. 2.1 Концепція технології LINQ
Спочатку підтримуючи механізм запитів для колекцій об'єктів в пам'яті, реляційних баз даних і даних у форматі XML, LINQ володіє розширюваною архітектурою, яка дозволяє стороннім розробникам реалізувати доступ до їх сховищ даних через механізм LINQ. Для цього необхідно реалізувати стандартні оператори запитів, використовуючи методи розширення, або реалізувати інтерфейс IQueryable, що дозволяє розбирати дерево вираження під час виконання, транслюючи його в свою мову запитів. У спільноті існує приклад користувальницької реалізації стандартних операторів запитів. Наприклад, LINQ to SQL, який перетворює LINQ-вирази в SQL-запити до бази даних, використовує можливості компілятора для побудови дерева виразів, грунтуючись на контексті програми, а не створюючи делегати функцій. Отримавши дерево виразів, що описує запит, спеціалізований провайдер бази даних може його проаналізувати і перетворити в запит на відповідній мові для бази даних, наприклад Microsoft SQL Server, Jet (яка використовується в Microsoft Access) або будь-який інший [6, 7].
Більшість інструментів ORM
намагаються абстрагувати фізичну базу даних у вигляді бізнес-об'єктів. З такою
абстракцією іноді втрачається можливість виконання запитів SQL, які становлять
значну частину абстракції реляційних баз даних. Саме це відрізняє LINQ to SQL
від більшості його аналогів. Ми не тільки отримуємо зручність у вигляді
бізнес-об'єктів, які відображаються на базу даних, але також отримуємо
повноцінну мову запитів, подібний SQL, приклад якої дуже добре зображено на
рисунку 2.2.
Рис. 2.2 Концепція роботи LINQ to
SQL
У LINQ to SQL модель даних реляційної бази даних зіставляється об'єктної моделі, вираженої в мові програмування розробника. При виконанні програми LINQ to SQL перетворює інтегровані в мову запити з об'єктної моделі в SQL і відправляє їх до бази даних для виконання. Коли база даних повертає результати, LINQ to SQL перетворює їх назад в об'єкти, з якими можна працювати на власній мові програмування.
Користувачі середовища Visual Studio, як правило, користуються конструктором Реляційний конструктор об'єктів, який надає користувальницький інтерфейс для реалізації багатьох функцій LINQ to SQL[7].
Загалом, LINQ to SQL - інструмент ORM початкового рівня, що дозволяє виконувати потужні SQL-запиту.
Технологію LINQ to SQL часто використовують в розробках програмного забезпечення. Під час навчання про цю технологію згадають поверхнево, та не розглядають основних принципів на яких базується ця технологія та механізмів її роботи. Доцільність розробки засобу візуалізації, полягає в надані студентам знань та навичок використання технології LINQ to SQL при створенні програмного забезпечення візуалізуючи процеси роботи технології LINQ to SQL.
Методика застосування LINQ to SQL при розробці програмного забезпечення засобами Visual Studioto SQL - складна тема, і будь-які приклади вимагають участі багатьох елементів LINQ to SQL.- це клас, який встановлює з'єднання з базою даних. Він також надає кілька служб, які зображені на рисунку 2.3, що забезпечують відстеження ідентичності, відстеження змін і обробку цих змін.
У LINQ to SQL прийнято використовувати клас, похідний від DataContext. Ім'я похідного класу зазвичай збігається з ім'ям бази даних, на яку він відображається. Нехай на цей похідний клас будемо посилатися як на [Your] DataContext, оскільки його ім'я залежить від бази даних, для якої він створений.
У наведених прикладах похідний від
DataContext клас буде називатися Northwind. Для його побудови застосовувався
інструмент SqlMetal, що входить до складу Visual Studio, який генерує класи
відображення на основі бази даних SQL Server.
Рис. 2.3 Концепція функцій
DataContext
Цей похідний від DataContext клас, [Your]DataContext, зазвичай буде мати загальнодоступне властивість Таblе <Т> для кожної таблиці бази даних, яка відображається на базу даних, де Т - тип сутнісного класу, екземпляр якого створюється для кожного витягнутого записису з конкретної таблиці бази даних.
Тип даних Table <T> являє собою спеціалізовану колекцію. Наприклад, оскільки в базі Northwind присутній таблиця Customers, клас Northwind, успадкований від класу DataContext, матиме Table <Customers> по імені Customers. Це означає, що звертатися до записів в таблиці Customers бази даних можна, безпосередньо звертаючись до властивості Customers типу Table <Customers> в класі Northwind [4, 5].
Квінтесенція LINQ to SQL полягає у відображенні сутнісних класів на таблиці бази даних і властивостей сутнісних класів на стовпці таблиць бази даних.
Таке відображення може виникати безпосередньо у вихідних файлах класу за рахунок оснащення їх відповідними атрибутами або ж може бути задане в зовнішньому XML-файлі відображення. При використанні такого зовнішнього файлу специфічна для LINQ to SQL інформація може зберігатися окремо від вихідного коду. Це може бути дуже зручно, якщо немає вихідного коду або якщо потрібно зберігати код окремо від LINQ to SQL.
У більшості прикладів, присвячених LINQ to SQL, використовуються сутнісні класи, згенеровані інструментом командного рядка SQLMetal. Цей інструмент генерує сутнісні класи з інформацією про відображення LINQ to SQL, вбудованої безпосередньо в генеруються вихідні модулі. Ця інформація представлена у формі атрибутів і їх властивостей.
Сутнісні класи мають ім'я у формі однини від імені таблиці бази даних Northwind. Наприклад, клас на ім'я Customer. Оскільки Customer-форма однини від Customers, а в базі даних Northwind є таблиця по імені Customers, це вказує на те, що Customer - сутнісний клас для таблиці Customers з бази даних.
Інструмент командного рядка SQLMetal підтримує опцію, яка викликає іменування сутнісного класу у формі однини імені таблиці бази даних. Якщо при генерації сутнісних класів ця опція не вказана, то клас отримав би ім'я Customers, а не Customer, бо такий ім'я таблиці - Customers. Сутнісний клас може мати ім'я як у множині, так і в однині.
Асоціація (association) - це термін,
використовуваний для призначення первинного ключа для відносин зовнішнього
ключа між двома сутнісними класами, які зображені на рисунку 2.4.
Рис. 2.4 Зв'язок між двома
сутнісними класами
Відносно "один до багатьох" результатом асоціації є те, що батьківський клас - той, що містить первинний ключ - включає колекцію дочірніх класів, тобто класів, які мають зовнішній ключ. Ця колекція зберігається в приватній змінній типу EntitySet <T>, де Т буде типом дочірнього сутнісного класу.
Перевага асоціації полягає в можливості доступу до дочірніх об'єктів батьківських і, таким чином, до записів бази даних, з тією ж легкістю, як до будь-якого властивості батьківського об'єкта. Аналогічно доступ до батьківського об'єкту з дочірнього полягає у зверненні до відповідного властивості дочірнього об'єкта.
Однією з цінних служб, що надаються вам DataContext, є обробка змін. Коли ви намагаєтеся оновити базу даних викликом методу SubmitChanges класу DataContext, він автоматично виконує оптимістичне виявлення конфліктів паралельного доступу.
Якщо конфлікт виявлений, генерується виключення ChangeConflictException. Кожен раз, коли ви викликаєте метод SubmitChanges, потрібно вміщувати його в блок try/catch і перехоплювати виключення ChangeConflictException. Це - правильний спосіб виявлення конфліктів паралельного доступу.
Як тільки конфлікт паралелізму виявлений, наступний крок полягає в його вирішенні. Це можна зробити декількома способами.
Наприклад, за рахунок виклику методу ResolveAll колекції ChangeConflicts успадкованого класу DataContext, коли перехоплено виняток ChangeConflictException.
Властивість Log об'єкта DataContext використовується для відображення трансльованого запиту SQL. Це може бути дуже корисно не тільки з метою налагодження, але і для аналізу продуктивності. Ви можете виявити, що запити LINQ to SQL транслюються в дуже неефективні запити SQL. Або ж з'ясувати, що через відкладене завантаження асоційованих сутнісних класів доводиться виконувати більше SQL-запитів, ніж необхідно. Властивість DataContext.Log забезпечить отримання такої інформації.
Метод GetChangeSet() об'єкта DataContext можна використовувати для отримання всіх сутнісних об'єктів, що містять зміни, які повинні бути збережені в базі даних при виклику SubmitChanges. Це зручно для протоколювання і налагодження.
Без сумнівів, однією з головних труднощів використання будь-якого інструменту ORM є управління змінами в базі даних. Якщо ви тримаєте всю логіку бізнес-класів і логіку LINQ to SQL в одних і тих же модулях, то цим створюєте собі проблеми супроводу при змінах бази даних.
Розгляньте можливість застосування часткових класів, поміщаючи бізнес-логіку в модуль, окремий від модулів згенерованих сутнісних класів. Використовуючи часткові класи для зберігання ваших атрибутів бази даних LINQ to SQL окремо від бізнес-логіки, ви мінімізуєте необхідність у додаванні коду до будь-якого згенеровані сутнісному класу.
В якості альтернативи можна розділити бізнес-класи та відображення сутностей LINQ to SQL за допомогою зовнішнього XML-файла відображення. Йдеться про XML-файли, який відображає бізнес-об'єкти на базу даних, не покладаючись на атрибути LINQ to SQL.
Часткові методи дозволяють втручатися в певні події, які відбуваються в сутнісних класах. Витонченість їх у тому, що якщо тіло часткового методу вирішено не реалізовувати, то при цьому не виникне жодних накладних витрат, і компілятор не буде генерувати код, пов'язаний з їх викликом.
Засоби опанування використання технології LINQ to SQL
У додатках часто використовуються дані з баз даних SQL або XML-документів. Зазвичай, розробники повинні були вивчати окрім основної мови програмування, такої як наприклад C#, так і додаткову як SQL. LINQ (Language-Integrated Query) надає можливість здійснювати запити на самій мові C#. Тепер, замість вивчення окремої мови запитів, можна виконувати запити до баз даних SQL, наборам даних ADO.NET, XML-документами і будь-яким класам колекцій. NET Framework, що реалізують інтерфейс IEnumerable, використовуючи знання C# і декількох додаткових ключових слів і основних понять.
Використовуйте LINQ to SQL для доступу до баз даних SQL Server і SQL Server Express через строго типізований об'єктний шар, який створюється за допомогою об'єктно-реляційного конструктору. Його можна використовувати для порівняння класів LINQ to SQL таблиць в базі даних і потім створювати запити LINQ для прив'язки даних до елементів управління у додатку.
Об'єктно-реляційний конструктор надає візуальну область конструктора для створення класів сутностей і асоціацій (відносин) LINQ to SQL, які базуються на об'єктах в базі даних. Іншими словами, Об'єктно-реляційний конструктор використовується для створення моделі об'єкта в додатку, яка співставляється з об'єктами в базі даних. Модель також генерує DataContext із суворим контролем введення, який використовується для відправки та отримання даних між класами сутностей і базою даних. Об'єктно-реляційний конструктор генерує DBML-файл, який забезпечує співставляється між класами LINQ to SQL та об'єктами бази даних. Реляційний конструктор об'єктів також генерує DataContext і класи сутностей.
Після додавання елемента LINQ to SQL Classes в проект і відкриття об'єктно-реляційного конструктору, порожня область конструктора представляє порожній DataContext, готовий до конфігурації. DataContext конфігурується з інформацією про підключення, наданої першим елементом, який був перетягнути в область конструктора. Тому DataContext конфігурується з використанням інформації про підключення з першого переміщеного в область конструктора елемента.
Можна створювати класи сутностей, які зіставляються таблиць бази даних і уявленням, шляхом перетягування таблиць оглядача бази даних на об'єктно-реляційний конструктор. конфігурується з інформацією про підключення, наданої першим елементом, який переміщений в область конструктора. Якщо в об'єктно-реляційний конструктор додається елемент, який використовує інше підключення, то можна змінити підключення для DataContext.
Можна створювати методи DataContext, які викликають збережені процедури і функції. Крім того, можна також призначати збережені процедури, які можуть використовуватися для поведінки за замовчуванням при LINQ to SQL середовища виконання, яка виконує Вставки, Оновлення та видалення.
Подібно іншим об'єктам, LINQ to SQL класи можуть використовувати спадкування і виводитися з інших класів. Об'єктно-реляційний конструктор забезпечує властивості контекстного простору імен і Простору імен сутностей на DataContext. Ці властивості визначають, який простір імен DataContext та коду класів сутностей генерується в ньому. За замовчуванням ці властивості порожні і DataContext класи сутностей генеруються в просторі імен додатки. Щоб згенерувати код у простір імен, відмінне від простору імен додатки, введіть значення в властивості Контекстне простір імен та/або простір імен сутностей [6, 7].