Динамічне створення Windows і Web CRUD-інтерфейсів і не тільки для бізнес-додатків з XAF + Entity Framework. Частина 1

Історія

У нас є старенька веб додаток DXLibrary для обліку літератури та пошуку цікавих поповнень в місцевій бібліотеці, написаний багато років тому за пару годин одним з розробників на DevExpress eXpressApp Framework (XAF). Дані програми зберігаються в Microsoft SQL Server бази, а робота з ними ведеться через DevExpress eXpress Persistent Objects ORM (між .xpo). Так як це чудо досі стерпно выполнет свої неабиякі функції, так що мені захотілося трохи освіжити його інтерфейс під поточні реалії. Крім фейсліфтингу хочеться змінити між .xpo на Microsoft ADO.NET Entity Framework (EF) під капотом.imageОсновним мотивом тут для мене є не те, що EF щось краще або гірше (обидві ORM давно довели, що відмінно підходять для своїх завдань), а те, що досі на Хабре не було російськомовного туториала по інтеграції XAF і EF, хоча вони вже «не перший рік замужем». Є величезне бажання заповнити цей пробіл + елементарно було кілька запитів від користувачів «бібліотекаря», які можна заодно запив у новій версії. Нарешті, з версії 15.1 XAF надає оновлений веб інтерфейс, заточений у тому числі для touch-пристроїв, який хотілося б зайвий раз показати спільноті, що гріха таїти:-)

Це перша і вступна частина із серії постів, де я спробую показати по кроках варіант прискореної генерації веб, так і настільних line-of-business (LOB) додатків на базі існуючої або готової моделі Entity Framework, що представляє структуру даних вищеописаною предметної області. Користувальницький інтерфейс буде створюватися автоматично на базі міксу технологій ASP.NET WebForms/HTML5 і WinForms, а також відповідних візуальних компонент DevExpress, скомпонованих разом в рантайм під чуйним керівництвом XAF — нашого UI фреймворку (дізнатися більше на Хабре, сайт), а по суті сформованого за майже 10 років існування і постійно розширюваного набору best patterns & practices для швидкого створення Office-like бізнес додатків .NET розробників.


Мінімальні вимоги для проходження

1. .NET Framework 4+ і Visual Studio 2010+ (підтримуються повні і Community Edition версії, крім express) – далі я буду використовувати Visual Studio 2013.
2. Entity Framework 6 Tools (в залежності від версії студії можуть бути вбудованими або вимагати окремої установки
3. Полня версія DevExpress XAF v15.1 (а краще 15.2, якщо є доступ до беті), або 30-денна пробна, яка гойдається з нашого сайту безкоштовно, без реєстрації і СМС:-) і ставиться за пару хвилин на SSD.
4. Microsoft SQL Server для зберігання даних (підійдуть будь-які повні/express/localdb версії починаючи з 2000) або інший провайдер БД, підтримуваний EF.

Перед тим як почати, мої роздуми на тему такого роду фреймворків, можливостей кастомізації і вибору ORMВажливо розуміти, що XAF по своїй суті не є code generator, як, наприклад, наші схожі продукти DevExpress MVVM Framework & Scaffolding Wizard для WPF/WinForms. Навпаки, XAF є справжнім динамічним application framework, який генерує користувальницький інтерфейс по певним правилам повністю під час виконання. Так вам не доведеться руками перезапускати генерацію форм після кожної зміни вашої вихідної моделі даних (таких, як додавання нового класу або властивості), або втрачати раніше написаний в згенерованих формах кастомный код — після запуску XAF додатка ви завжди автоматично отримаєте актуальний результат скаффолдинга UI і БД по вашій поточній структурі даних і набору правил. Практично це означає, що за замовчуванням в XAF не генерується ніякої вихідний код CRUD форм, до якого розробник б мав прямий доступ в студії, як це відбувається у звичайній розробці клієнтських додатків. Хоча розробник XAF все-таки має повний контроль над кінцевими цеглинках UI типу System.Windows.Forms.Control або HTML елементами і може ними маніпулювати як в будь-якому іншому .NET додатку, більшу частину часу натуральний процес XAF розробки представляє з себе налаштування системи на більш високому рівні, часто через структури дата моделей, крос-платформні метадані або абстракції типу View, Property Editor, Controller та ін. Повторюся, що доступ на низький рівень є, вас ніхто не обмежує, можна також міксувати підходи, але потрібно це набагато рідше, а інакше який тут виграш у порівнянні з традиційною розробкою? Повинен зізнатися, що в цьому і полягає одночасно найбільша радість і недолік XAF, так як спочатку людям складно перебудуватися і абстрагуватися від оперування візуальними контролами безпосередньо. Звідси і крута крива навчання на перших етапах.

Напевно, також відразу варто розвіяти сумніви з приводу можливостей UI і кастомізації під різні потреби замовника в такого роду RAD тулзах, як мовиться, не квадратно-гніздовим єдиним! Щоб краще уявити UI типових бізнес-додатків, які можуть бути створені за допомогою фреймворку, можна подивитися готові скріншоти на сторінці продукту тут, потикати наживо демки онлайн (або краще з інсталяції, щоб і десктопні демки охопити заодно) і, нарешті, подивитися в Інтернеті приклади продакшн додатків від реальних замовників, наприклад, ось хороший приклад або ось парочка від знайомої багатьом в СНД Галактики з їх AMM, CnP, EAM та ін. рішеннями (раз, два). Останні, до речі, вийшли з «галактичного» тюнінг-ательє:-) XAFARI — набору додаткових модулів і компонет під платформу XAF. Крім комерційних third-party розширень, не можна не згадати і безкоштовний проект http://www.expandframework.com, який вже 5 років розвивається силами спільноти. Тут же відзначу, що багато в чому завдяки використанню візуальних компонент DevExpress працювати з створеними додатками цілком можливо, як і на звичайному десктопі, так і на touch-пристроях з меншим екраном, наприклад, планшетах, при мінімумі додаткових налаштувань з боку розробника (причому навіть в старому-доброму WinForms!), але про це пізніше.

Якщо у вас ще немає готового багажу знань якийсь ORM, то перш ніж почати роботу з XAF, вас напевно буде мучити складний вибір. З одного боку, маємо справу з між .xpo простий і досі здорової пропрієтарної ORM бібліотекою (дізнатися більше російськомовних оглядів спільноти: раз, два), яка з 2006 року була єдиною вибором для XAF, з величезним числом прикладів, документації, відео, безкоштовної гарантованою підтримкою від компанії-розробника, а з іншого — рекомендована опенсорсная технологія для доступу до даних .NET з великим числом розробників на ринку праці, хорошим просуванням і розвитком від Microsoft, підтримкою сторонніх компаній, а також не меншою базою знань і технічною підтримкою силами спільноти на StackOverFlow, Social.MSDN, forums.asp.net (правда, без гарантії швидкого відповіді або відповіді взагалі). Ми проводили опитування серед своїх нових користувачів і виявилося, що для багатьох при інших рівних досить суттєвим фактором при виборі технології виявляється наявність гарантованої технічної підтримки (тут мається на увазі допомогу в разі проблем чи питань щодо того як краще зробити), а не факт, що десь там більше або менше якихось функцій. Технічно, якщо не брати до уваги факт, що формально EF підтримується XAF пізніше між .xpo з 2012 року, то підтримка двох бібліотек на рівні самого XAF та його модулів порівнянна по функціоналу і охоплюваних сценаріями. У даний момент частка наших EF користувачів росте, але все ще пристойно поступається між .xpo. Думається, реліз EF7 і також вирівнювання за наявності прикладів на нашій стороні ще змінить це співвідношення. Більше думок і відгуків наших користувачів на дану тему можна знайти в моєму блозі по темі.


Кроки по створенню нового XAF рішення з Entity Framework 6

0. Завантажити пробну версію з нашого сайту, дочекаємося успішної установки і запустимо Visual Studio;

1. Запустимо майстер створення нового проекту з іменем DXLibraryV2 через стандарное FILE | New | Project..., скориставшись пошуком і вибравши XAF Solution Wizard (або спочатку викликавши спеціальне DEVEXPRESS | All Platforms | New Project… меню студії
(показати...)

2. У запустившемся майстрі виберемо платформу Windows та Web і натиснемо Next
(показати...)

3. Виберемо Entity Framework Code First для доступу до даних і натиснемо Next(показати...)

4. Виберемо Authentication = Active Directory, що означає вхід в програму за поточним Windows користувачеві і натискаємо Next(показати...)

5. Завершимо роботу натисканням на Finish, так як поки нам не потрібні ніякі додаткові модулі(показати...)


Основні частини створеного XAF рішення

В результаті візард створить нам заготовки для майбутніх додатків відповідно до обраних раніше налаштувань:



У двох словах, у нас вийшло:
  • DXLibraryV2.Module — один крос-платформний модуль, що містить шаренный код для всіх платформ (наприклад, бізнес-логіка, моделі даних, налаштування метамоделі UI, робота з базою і в рідкісних випадках універсальні UI редактори)
  • DXLibraryV2.Module.Wxx — пара платформно-залежні модулі, де можуть жити код і налаштування, специфічні для якоїсь платформ
  • DXLibraryV2.Wxx — по одному виконуваному додатку на кожну платформу, тобто ASP.NET сайт і WinForms додаток. За замовчуванням ці програми будуть з'єднуватися з Microsoft SQL Server для зберігання даних по connectionString конфігураційних файлів додатків (Web.config і App.config).
Для зручності, проекти містять підпапки з промовистими іменами і readme.txt файли, які можуть допомогти не заблукати навіть самим суворим новачкам (дізнатися більше...).

Якщо ми прямо зараз запустимо DXLibraryV2.Web і DXLibraryV2.Win з Visual Studio, то отримаємо працюють болванки додатків для веб браузера (ASP.NET WebForms) і десктопа (WinForms), які поки що нічого особливого не навчені, ну хіба що крім CRUD управління користувачами, ролями і налаштуваннями системи безпеки – така собі простенька адмінка за хвилину:




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

Особливості Entity Framework інтеграції

Перш за все, основна підтримка Entity Framework XAF реалізована в збірках DevExpress.ExpressApp.EF.v15.1.dll (для .NET 4.0) і DevExpress.ExpressApp.EF.45.v15.1.dll (для .NET 4.5), які автоматично посилаються в XAF проектах в залежності від версії .NET Framework. Якщо ви використовуєте наш майстер зі створення проектів, то всі необхідні EF залежно додаються автоматично. Якщо немає, то їх завжди можна додати в проекти стандартним способом через NuGet.

На момент написання статті остання XAF версія підтримує Entity Framework 6, охоплюючи як code-based стратегії з використанням DbContext так і застарілу стратегію на базі ObjectContext EntityObject (в старих версіях також є підтримка EF 5). За статистикою, серед наших користувачів популярність останнього підходу до розробки моделі даних сильно поступається першому, а після чуток про ймовірне вбитий EDMX в наступної генерації EF думаю вона взагалі зійде нанівець. Офіційної підтримки останніх бет EF 7 на даний момент у нас немає зважаючи постійних змін, хоча вже ведуться роботи в даному напрямку. Сама по собі нова генерація EF вже зараз містить багато цікавих можливостей для нас і наших користувачів і виглядає дуже перспективною.

Технічно, робота з EF Code First означає, що у нас повинні бути POCO бізнес-класи, що визначають структури нашої моделі даних, і спадкоємець від DbContext, що містить необхідний набір типізованих колекцій бізнес сутностей DbSet, які можуть бути запитані з бази. Ви ще пам'ятаєте, що на 5м кроці ми вибрали тип аутентифікації користувачів (AuthenticationActiveDirectory), тим самим активувавши вбудований модуль системи безпеки (SecurityModule)? Так ось, в результаті цього майстер проекту включив до нашого спадкоємця DbContext (DXLibraryV2.Module\BusinessObjects\DXLibraryV2DbContext.cs) необхідні вбудовані сутності User, Role (а також ін. сервісні запчастини), оголошені в опціональною бібліотеці DevExpress.Persistent.BaseImpl.EF.v15.1, що йде як частина стандартної поставки XAF і містить готові класи для типових випадків.



Вищезазначені сутності є абсолютно звичайними POCO класами, визначальними якусь структуру даних і логіку, наприклад:



Далі тип інтерфейсу DbContext або ObjectContext (у разі EDMX стратегії) разом з обраної рядком підключення до бази даних, взятої з конфігураційних файлів виконуваних додатків, передається у EFObjectSpaceProvider при налаштуванні доступу до даних у спадкоємців WebApplication (DXLibraryV2.Web\WebApplication.cs) або WinApplication (DXLibraryV2.Win\WinApplication.cs).

public partial class DXLibraryV2WindowsFormsApplication : WinApplication {
public DXLibraryV2WindowsFormsApplication() {
InitializeComponent();
}
protected override void CreateDefaultObjectSpaceProvider(CreateCustomObjectSpaceProviderEventargs args) {
args.ObjectSpaceProvider = new EFObjectSpaceProvider(
typeof(DXLibraryV2DbContext),
TypesInfo, null, 
args.ConnectionString
);
}

WxxApplication класи представляють із себе виконувані програми для кожної з платформ та пов'язані з ними послуги. Їх примірники створюються і змінюються при кожному запуску у вхідних точках додатків, наприклад, у методі Session_Start з DXLibraryV2.Web\Global.asax.cs або методі Main з DXLibraryV2.Win\Program.cs. Серед необхідних налаштувань програми крім компонентів системи безпеки і рядка з'єднання присутня список залежних модулів, який може складатися як з сторонніх так і з наших власних модулів, наприклад типу DXLibraryV2Module (DXLibraryV2.Module\Module.cs). XAF модулі (спадкоємці від ModuleBaseяк і самі програми (спадкоємці XafApplication) є налаштованим похідними від System.ComponentModel.Component, для яких також доступні візуальні дизайнери.



Спеціально для першого запуску додатків майстром був закодований тестовий набір даних у методі UpdateDatabaseAfterUpdateSchema спадкоємця ModuleUpdater (DXLibraryV2.Module\DatabaseUpdate\Updater.cs) — аналога методу Seed у EFских database initializerов.



В результаті відпрацювання методів ModuleUpdater-ів і пов'язаного коду фреймворком була створена нова база даних Microsoft SQL Server і відповідні таблиці з записами:



EFObjectSpaceProvider незалежно від вибору code-based або EDMX стратегій працює з ObjectContext API, що є для них спільним знаменником, адже всередині DbContext в EF 6 поки ще містить у собі ObjectContext, доступ до якого можна одержати через приведення до IObjectContextAdapter. Зокрема, ми використовуємо його MetadataWorkspace для рефлексії інформації про типах і їх структурі для подальшої побудови скелета CRUD користувальницького інтерфейсу.

Як ви могли помітити з прикладу коду в ModuleUpdater вище, у контексті XAF CRUD операції рекомендується проводити не безпосередньо через DbContext/ObjectContext, а через цю абстрактну сутність IObjectSpace або в нашому випадку її конкретну реалізацію для Entity Framework — EFObjectSpace. Він поставляється вищезазначеним EFObjectSpaceProvider і використовує у себе всередині ObjectStateManager і CreateQuery API, щоб модифікувати або зчитувати дані. IObjectSpace по суті є ORM-незалежним втіленням патернів Repository та Unit Of Work, а технічно просто обгорткою над контекстом даних. Працюючи через IObjectSpace API, ви можете раз написавши якусь бізнес логіку, мігрувати її на іншу ORM без змін. Більш важливо, що за допомогою IObjectSpace інтерфейсна частина XAF взаємодіє з даними, наприклад, отримує або «слухає» зміни і оновлює себе відповідно.

Практичні нотатки на майбутнє

1. Під час розробки та відлагодження програми з тестової БД після постійних правок структури дата модельних класів зручно тимчасово відключати Code First Migrations фічу ЕF, прописуючи потрібний database initializer з допомогою вбудованого API з System.Data.Entity, наприклад ось так (DXLibraryV2.Module\Module.cs):
// Uncomment this code to delete and recreate the database each time the data model has changed.
// Do not use this code in a production environment to avoid data loss.
// #if DEBUG
// Database.SetInitializer(new DropCreateDatabaseIfModelChanges<DXLibraryV2DbContext>());
// #endif


2. Зовсім не обов'язково використовувати вбудовані класи User,Role з DevExpress.Persistent.BaseImpl.EF.v15.1– це в основному потрібно новачкам для швидкого «зльоту». XAF не є кінцевим продуктом і, в першу чергу — це гнучкий та розширюваний *фреймворк* для побудови додатків, в якому можна завжди замінити потрібні запчастини на свої або почати робити все «з нуля», якщо вже знаєш що та як. Так, наприклад, замість вбудованих запчастин системи безпеки ми могли запросто оголосити свої сутності згідно EF документації і додати їх у наш DbContext.

3. Для нормальної роботи багатьох стандартних сценаріїв бажано реалізовувати підтримку INotifyPropertyChanged у ваших бізнес класах (хоч вручну хоч з допомогою утиліт типу цієї, які автоматично инжектят потрібну реалізацію під час компіляції). На худий кінець можна вручну реалізувати наш спец. інтерфейс IObjectSpaceLink і руками кликати ObjectSpace.SetModified(this), щоб прокинути нотифікацію в потрібних місцях.

4. З досвіду, клієнти можуть (і хочуть) розміщувати бізнес логіку прямо в самих EF класах замість реалізації окремих контролерів або сервісів. Не в нашому праві їм забороняти (хоча на тему анемічній моделі vs багатою на Стеку купа холиваров, пам'ятаю навіть сам вкинув свої п'ять копійок тут) і для таких випадків крім вищезгаданого IObjectSpaceLink може бути зручний інтерфейс IXafEntityObject, який полегшує написання логіки на створення (OnCreated), завантаження (OnLoaded) і збереженні сутностей (OnSaving).

5. Якщо у вас залишилася готова бібліотека EF класів від ASP.NET MVC проекту, вам може бути важливо знати, що в даний момент у нас обмежена підтримка стандартних Data Annotations атрибутів впливають на вигляд інтерфейсу, наприклад DisplayFormat, UIHint. При цьому стандартні фреймворковские атрибути впливають на поведінку самого EF працюють як і повинні. Як би там не було, в XAF є купа своїх універсальних атрибутів на будь-який смак і колір, які дозволяють прискорити настройку UI і зв'язаної логіки в простих випадках. Забігаючи наперед варто відзначити, що загалом для такого завдання краще використовувати Application Model (ось тут вже розповідав детальніше).

висновок

Це, напевно, всі основні особливості інтеграції Entity Framework XAF, про які потрібно знати на даному етапі. Поглибити своє розуміння можна з допомогою нашої онлайн документації тут: eXpressApp Framework > Concepts > Business Model Design > Business Model Design with Entity Framework і eXpressApp Framework > Getting Started > Basic Tutorial (тут також міститься інформація про фреймворку і основні підходи в загальному). Також можуть знадобитися демки XCRM, EFDemoCodeFirst, EFDemoModelFirst, які можна знайти в %Public%\Documents\DevExpress Demos 15.1\Components\eXpressApp Framework\ і які являють собою досить складні і закінчені програми, що демонструють інтеграцію майже з усіма модулями фреймворка. Купа прикладів і відповідей в базі знань техпідтримки також не будуть зайвими до згадки.

У наступній серії ми будемо безпосередньо створювати модель даних EF по існуючій базі даних і також реалізовувати основну логіку роботи вихідного додатка-прототипу.

C повагою,
Денис

p.s.

Якщо вас зацікавили наші продукти і після їх більш детального вивчення протягом безкоштовного пробного періоду вам захочеться їх придбати, то до 20 грудня 2015 року включно ви можете скористатися десяти процентним купоном на покупку в рублях (~$220 або ~14тыс рублів за поточним курсом) нової ліцензії DevExpress Універсальний, що включає в себе XAF і купу інших інструментів для розробки під популярні платформи. Для цього вам потрібно буде перейти в магазин Softline.ru і після оформлення замовлення
ввести в спеціальне поле кодUniversal_XafEf

Окреме спасибі нашому реселлеру за те, що досить швидко вдалося домовитися про цієї акції на благо російськомовного співтовариства СНД в такий час. Якщо вам раптом зручніше придбати у валюті безпосередньо з нашого сайту, то для отримання аналогічної знижки, напишіть мені на пошту із вказанням посилання на цей пост. Туди ж можете надсилати будь-які питання по XAF, побажання або інформувати про можливі проблеми.

Джерело: Хабрахабр

0 коментарів

Тільки зареєстровані та авторизовані користувачі можуть залишати коментарі.