Please use this identifier to cite or link to this item: https://er.chdtu.edu.ua/handle/ChSTU/8580
Title: Спосіб модифікації методів платформи .NET для поліпшення читабельності коду
Authors: МИРОНЮК, Тетяна
АННАГЕЛДІЄВ, Байрамгелді
Keywords: .NET;C#;ORM;SQL;ПОКРАЩЕННЯ ЧАСУ РОЗРОБКИ;ПОКРАЩЕННЯ ПІДТРИМУВАННОСТІ КОДУ;ПРОГРАМНА РЕАЛІЗАЦІЯ;АРХІТЕКТУРА;ООП
Issue Date: 2023
Abstract: Досліджувана тема кваліфікаційної роботи бакалавра є актуальною через те, що сприяє полегшенню підтримуваності довготривалих проектів та зменшенню їх час розробки. Метою виконання кваліфікаційної роботи є модернізація існуючих методів та патернів на базі платформи .NET. Розроблена програмна реалізація являє собою бібліотеку до мови програмування C#. Реалізована бібліотека містить набір методів для покращення часу розробки та підтримуваності цього коду. Також для цієї бібліотеки був створений окремий проект з модульним тестуванням, який при зміні поточної версії бібліотеки перевіряє коректність роботи окремих ділянок кожного з алгоритмів, а також всіх алгоритмів в цілому. Вся архітектура проекту задовольняє особливості ООП проектів для забезпечення легкості вдосконалення та масштабування бібліотеки. Загальний обсяг роботи становить 77 сторінки. У кваліфікаційній роботі 37 рисунок, 1 таблиця. Для виконання роботи використано 15 літературних джерел.
URI: https://er.chdtu.edu.ua/handle/ChSTU/8580
Appears in Collections:123 Комп’ютерна інженерія (Комп'ютерні системи та мережі)

Files in This Item:
File Description SizeFormat 
01_ТИТУЛКА_Аннагелдієв-merged.pdf
  Restricted Access
3.02 MBAdobe PDFView/Open Request a copy


Items in DSpace are protected by copyright, with all rights reserved, unless otherwise indicated.

Extracted text
МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ
ЧЕРКАСЬКИЙ ДЕРЖАВНИЙ ТЕХНОЛОГІЧНИЙ УНІВЕРСИТЕТ
ФАКУЛЬТЕТ ІНФОРМАЦІЙНИХ ТЕХНОЛОГІЙ І СИСТЕМ
КАФЕДРА ІНФОРМАЦІЙНОЇ БЕЗПЕКИ ТА КОМП’ЮТЕРНОЇ ІНЖЕНЕРІЇ
ПОЯСНЮВАЛЬНА ЗАПИСКА
до кваліфікаційної роботи бакалавра
на тему:
«Спосіб модифікації методів платформи .NET для
поліпшення читабельності коду»
ЧДТУ.2319034.005 ПЗ
Виконав: студент 4 курсу, групи КМ-1905
спеціальності 123 – «Комп’ютерна інженерія»
за освітньою програмою – «Комп’ютерні системи
та мережі»
Байрамгелді АННАГЕЛДІЄВ
Керівник
к.т.н., доцент Тетяна МИРОНЮК
Рецензент
к.т.н., доцент, начальник відділу персоналу
ЗАЖОМА В.М.
«ЗАХИСТ ДОЗВОЛЯЮ»
Завідувач кафедри ІБ та КІ
д.т.н., професор ______ Володимир РУДНИЦЬКИЙ
Черкаси 2023 року
Форма № Н-9.01
ЧЕРКАСЬКИЙ ДЕРЖАВНИЙ ТЕХНОЛОГІЧНИЙ УНІВЕРСИТЕТ
Факультет: інформаційних технологій і систем
Кафедра: інформаційної безпеки та комп’ютерної інженерії
Освітньо-кваліфікаційний рівень: Бакалавр
Спеціальність 123 – Комп’ютерна інженерія
Освітня програма Комп’ютерні системи та мережі
«ЗАТВЕРДЖУЮ»
Завідувач кафедри ІБ та КІ
д.т.н., професор _____________ Рудницький В.М.
«28» лютого 2023 року
ЗАВДАННЯ
на кваліфікаційну роботу бакалавра студенту
Аннагелдієву Байрамгелді
(прізвище, ім‘я, по батькові)
1. Тема роботи: Спосіб модифікації методів платформи .NET для поліпшення
читабельності коду
Керівник роботи: к.т.н. Миронюк Тетяна Василівна
(прізвище, ім’я, по батькові, науковий ступінь, вчене звання)
затверджені наказом університету від «24» лютого 2023 р. № 43/04
2. Строк подання студентом роботи:
3. Вихідні дані до роботи:
 методи роботи з базою даних: на базі платформи .NET;
 типи підтримуваних даних: всі типи даних;
 платформа: Windows 7, Windows 8, Windows 10, Ubuntu;
 мова програмування: C#;
 інтегроване середовище розробника: Visual Studіo 2019.
4. Зміст розрахунково-пояснювальної записки (перелік питань, що їх належить розробити):
Вступ
1 Аналоги та характеристика платформи .NET.
2 Аналіз існуючих програмних рішень для платформи .NET
3 Програмне вдосконалення існуючих методів та патернів розроблених на базі
платформи .NET
Висновки
Додатки
Список використаних джерел
5. Перелік графічного матеріалу (з точним зазначенням обов’язкових креслень, плакатів):
1. Специфікація
2. Текст програми
6. Консультанти розділів роботи:
Розділ Прізвище, ініціали Підпис, дата
консультанта завдання видав завдання прийняв
7. Дата видачі завдання: 27 лютого 2023 року
КАЛЕНДАРНИЙ ПЛАН
Термін
№ з/п Назва етапів роботи виконання Примітка
етапів роботи
1 Отримання завдання 01.03 – 14.03 виконано
2 Збір матеріалу 15.03 – 1.04 виконано
3 Обробка матеріалу 02.04 – 10.04 виконано
4 Вибір програмного забезпечення та його виконано
обґрунтування 11.04 – 15.04
5 Розробка програмного продукту 16.04 – 26.04 виконано
6 Розробка бази даних 27.04 – 05.05 виконано
7 Синхронізація програмного продукту з базою 06.05 – 11.05 виконано
даних та тестування програмного продукту
8 Оформлення пояснювальної записки 12.05 – 22.05 виконано
9 Оформлення графічного матеріалу 22.05 – 31.05 виконано
10 Подання кваліфікаційної роботи на відгук та 01.06.23 виконано
рецензування
11 Захист кваліфікаційної роботи 07.06.23
Студент ____________________________ Байрамгелді АННАГЕЛДІЄВ
(підпис)
Керівник роботи _____________________________ Тетяна МИРОНЮК
(підпис)
АНОТАЦІЯ
Досліджувана тема кваліфікаційної роботи бакалавра є актуальною
через те, що сприяє полегшенню підтримуваності довготривалих проектів та
зменшенню їх час розробки.
Метою виконання кваліфікаційної роботи є модернізація існуючих
методів та патернів на базі платформи .NET.
Розроблена програмна реалізація являє собою бібліотеку до мови
програмування C#. Реалізована бібліотека містить набір методів для
покращення часу розробки та підтримуваності цього коду. Також для цієї
бібліотеки був створений окремий проект з модульним тестуванням, який
при зміні поточної версії бібліотеки перевіряє коректність роботи окремих
ділянок кожного з алгоритмів, а також всіх алгоритмів в цілому. Вся
архітектура проекту задовольняє особливості ООП проектів для забезпечення
легкості вдосконалення та масштабування бібліотеки.
Загальний обсяг роботи становить 77 сторінки. У кваліфікаційній
роботі 37 рисунок, 1 таблиця. Для виконання роботи використано 15
літературних джерел.
Ключові слова: .NET, C#, ORM, SQL, ПОКРАЩЕННЯ ЧАСУ
РОЗРОБКИ, ПОКРАЩЕННЯ ПІДТРИМУВАННОСТІ КОДУ, ПРОГРАМНА
РЕАЛІЗАЦІЯ, АРХІТЕКТУРА, ООП.
ANNOTATION
The research topic of the bachelor's qualification work is relevant due to
the fact that to facilitate the maintenance of long-term projects and reduce their
development time.
The purpose of the qualification work is to modernize existing methods and
patterns based on the .NET platform.
The developed software implementation is a library for the C #
programming language. The implemented library contains a set of methods to
improve the development time and maintenance of this code. Also for this library
the separate project with modular testing which at change of the current version of
library checks correctness of work of separate sites of each of algorithms, and also
all algorithms as a whole was created. The entire architecture of the project
satisfies the features of OOP projects to ensure ease of improvement and scaling of
the library.
The total volume of the work is 77 pages. In the qualifying work 37
figures, 1 table. 15 literary sources were used to perform the work.
Keywords: .NET,C #, ORM, SQL, IMPROVEMENT OF
DEVELOPMENT TIME, IMPROVEMENT OF CODE SUPPORT, SOFTWARE
IMPLEMENTATION, ARCHITECTURE, OOP.
ЗМІСТ
ВСТУП..................................................................................................................... 4
РОЗДІЛ 1 АНАЛОГИ ТА ХАРАКТЕРИСТИКА ПЛАТФОРМИ .NET.............6
1.1 Огляд програмної платформи «.NET» ...................................................... 6
1.2 Мова програмування C# та платформа .NET...........................................9
1.3 Порівняльний аналіз мови програмування C# з іншими мовами.........10
РОЗДІЛ 2 АНАЛІЗ ІСНУЮЧИХ ПРОГРАМНИХ РІШЕНЬ ДЛЯ
ПЛАТФОРМИ .NET..............................................................................................15
2.1 Поняття репозиторію для платформи .NET............................................15
2.2 Порівняння різних типів ORM платформи .NET...................................17
2.3 Базова логіка технології EntityFrameworkCore.......................................24
РОЗДІЛ 3 Програмне вдосконалення ІСНУЮЧИХ МЕТОДІВ ТА ПАТЕРНІВ
РОЗРОБЛЕНИХ НА БАЗІ ПЛАТФОРМИ .NET................................................31
3.1 Сортування та фільтрація для вдосконалення методів..........................31
3.2 Часткове оновлення сутностей в процесі модернізації методів...........35
3.3 Вдосконалення методів універсального репозиторію...........................39
ВИСНОВКИ...........................................................................................................58
ПЕРЕЛІК СКОРОЧЕНЬ ТА УМОВНИХ ПОЗНАЧЕНЬ……………………...60
ЧДТУ.2319034.005 ПЗ
Змн. Арк. № докум. Підпис Дата
РозрКобив Аннагелдієв Б. Спосіб модифікації методів Літ. Лист Листів
Керівник Миронюк Т.В. платформи .Net для поліпшення 2 77
Рецеанзент Зажома В.М. читабельності коду
Н.Контроль Гресько С.О. Кафедра ІБ та КІ
Пояснювальна записка
Затвфердив Рудницький В.М. гр. КМ-1905
е
д
р
а
К
К
-
0
6
ДОДАТКИ:
А – 482.ЧДТУ.39034-01 Спосіб модифікації методів платформи .Net
для поліпшення читабельності коду
ПЕРЕЛІК ВИКОРИСТАНИХ ДЖЕРЕЛ……………………………………….76
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 3
ВСТУП
На сьогодні проблема коштів для бізнесу є досить великою, оскільки в
період карантину, а особливо війни, люди втратили ті можливості, які мали
раніше, а саме, заробити гроші на свої ідеї, тобто, бізнес вмирає. Оскільки,
якщо порівнювати статистику попередніх років, то більшість з цих стартапів
просто не мають коштів для того, щоб розпочати свій бізнес. Яку саме
цінністьнесуть гроші для ІТ-бізнесу? І що, в свою чергу, значить ІТ –бізнес
для інших сфер? Це час протягом якого програміст встигає покрити
визначений бізнес-процес своєю ділянкою коду. Це також час протягом
якоготестувальник закінчує тестування визначеної сторінки. Це час протягом
якого менеджер проекту зможе розказати замовнику про його продукт. А це
означає, що для того, щоб збільшити попит, необхідно збільшити доступність
продукту, а це означає, що зменшення ціни часу являється першочерговим
при вирішені цієї проблеми.
Проаналізувавши, відкритісьогодні статистичні дані щодо, наприклад,
ціни для розробки мобільного додатку можна зробити висновок, що
більшість додатків, що реалізуютьсясьогодні, розробляються занадто
недбало, та не враховують вимогу масштабування, яка б збереглав
майбутньому більше грошей та часу.
Підсумовуючи вище сказане, можна визначити, що тема
кваліфікаційної роботи бакалавра «Спосіб модифікації методів
платформи .Net для поліпшення читабельності коду» являються на сьогодні
досить актуальною та полягає в аналізі методів платформи .NET.
Наведемо перелік задач, які необхідно виконати в процесі дослідження:
- на основі існуючих методів платформи дослідити ефективність їх
продуктивності, тобто наскільки дані методи є швидкими та гнучкими під
час розробки;
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 4
- дослідити основні переваги та недоліки існуючих методів та
привести приклади для їх вдосконалення;
- враховуючи визначені, в процесі дослідження, недоліки
вдосконалити метод покращення ефективності для швидкості реалізації
нових додатків;
- розробити програму у вигляді бібліотеки для мови програмування
C#для стандартного та вдосконаленого методів;
- провести оцінку ефективності вдосконаленого та стандартного
методів для покращення часу розробки та навести перелік їх недоліків.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 5
РОЗДІЛ 1 АНАЛОГИ ТА ХАРАКТЕРИСТИКА ПЛАТФОРМИ .NET.
1.1 Огляд програмної платформи «.NET»
.NET Framework – це програмна платформа, що була розроблена та
підтримується компанією Microsoft з 2002 року[1]. Для того, щоб бути
часткою даної платформи необхідно, щоб мова реалізувала в собі Common
Language Runtime (CLR). Найбільші відомі мови цієї платформи: С++ з
керованим кодом,C#, VisualBasic .NET та F#. CLR являється однією з
головних складових компонентів пакету Microsoft .NET Framework.
Архітектори платформи .NET реалізовують свою платформу за
специфікацією CLI (англ. Common Language Infrastructure), що являється
загальномовною специфікацією інфраструктури компанії Microsoft [2].
Насправді в процесі виконання програми в середовищі CLR невідомо,
на якій саме мові програмування розробником було написано вихідний код.
А це говорить про те, що можна обрати будь-яку мову програмування, що
дозволяє найлегше вирішити конкретну задачу. Реалізовувати програмне
забезпечення допустимо на будь-якій мові програмування, при умові, що
використовуваний компілятор даної мови підтримує CLR.
В роботі, що розглядається компілятори розглядаються як засіби
контролю синтаксису і аналізу «правильності коду». Компілятори
інспектують вихідний код, впевнюються, що написане все має якийсь сенс, а
потім генерують код, що показує рішення даного завдання. Різноманітні
мови програмування надають можливість реалізовувати програмне
забезпечення, при цьому використовуючи різний синтаксис. Не треба
недооцінювати саме значення вибору синтаксису для мови програмування.
Компанією Microsoft було розроблено компілятори для таких мов
програмування, що використовуються на цій платформі: C # , C ++ / CLI, F #,
VisualBasic і IronPython та IronRuby, що компілюються та асемблер
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 6
IntermediateLanguage (IL). Окрім Microsoft ще декілька компаній та
університетів розробили компілятори, що призначені для середовища
виконання CLR. Такими найбільш відомими компіляторами для даного
середовища виконання є: Caml, COBOL, Ada, APL, Haskell, Lexico, Eiffel,
Forth, Fortran, LISP, Mondrian, Oberon, Pascal, LOGO, Lua, Mercury, ML, RPG,
Scheme, Smalltalk, Perl, Php, Prolog та Tcl / Tk[2].
На рисунку 1.1 наведено схематично процес компіляції файлів з
вихідним кодом. Як показано на рисунку, вихідний код програми може бути
реалізовано на будь-якій мовою, що підтримує середовище виконання CLR.
Далі відповідний мові компілятор перевіряє синтаксис і аналізує вихідний
код програми. Незважаючи на тип компілятора, що використовується,
результатом компіляції буде керований модуль (managedmodule), що
являється стандартним виконуваним (portableexecutable, PE) файлом 32-
розрядної (PE32) або 64-розрядної Windows (PE32 +), що вимагає для свого
виконання CLR. Створені керовані збірки зазвичай використовують переваги
функції безпеки відомим як «запобігання виконання даних» (DEP) та
технологію ASLR (AddressSpaceLayoutOptimization) застосування яких
підвищує інформаційну безпеку для всієї системи [3].
Рисунок 1.1 – Процес компіляція вихідного коду в модулі, що
управляються
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 7
Кожен з компіляторів, що призначений для CLR, крім генерування IL-
коду, має також створювати повні метадані (metadata) для кожного окремого
керованого модуля [3].
Іншими словами, метадані - це певний набір таблиць даних, які
описують те, що визначено в модулі, такими прикладом може бути тип та їх
члени. У метаданих також присутні таблиці, які вказують, на що саме вказує
керований модуль, наприклад, на імпортовані типи членів таблиці. Також,
метадані надають можливість розширювати функції таких старих технологій,
як типів COM та файлів IDL. На відміну від бібліотек та типів IDL-файлів,
метадані завжди пов'язані з файлом, який містить IL-код [4].
Також, метадані надають можливість застосовуватися в декількох
напрямках. Виділимо декілька з цих напрямків:
1. Cередовище розробки Microsoft VisualStudio застосовує метадані
для полегшення написання коду;
2. Метадані усувають вимогу необхідності у заголовкових і
бібліотечних файлах під час компіляції;
3. Метадані надають дозвіл збирачеві сміття відслідковувати
життєвий цикл об'єктів;
4. Під час верифікації коду CLR використовує метадані, для того, щоб
впевнитися, що код виконує лише «безпечні по відношенню до типів»
операції. Метадані дозволяють серіалізувати поля об'єкта, а далі передати
отримані дані по мережі на віддалений комп'ютер, а вже там провести процес
де серіалізації, при цьому відновивши об'єкт і його стан на віддаленому
комп'ютері.
Але виходячи з отриманих результатів може виникнути стурбованість
відносно того, що IL для їх алгоритмів не забезпечує достатнього рівню для
захисту інтелектуальної власності. Кажучи іншими словами, розробники
вважають, що хто-небудь інший може скористатися дизасемблером IL,
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 8
взявши побудований ними керований модуль і легко відновивши логіку коду
для програми.
Оскільки, IL-код працює на більш високому рівні, в порівнянні з
більшістю інших асемблерів, а тому дизасемблювання IL-коду виконується
дуже просто. Але при розробці коду, що працює на стороні сервера збірка
розташовується на сервері куди крім розробника немає доступу ніхто, а тому
IL знаходиться в повній безпеки.
І все ж таки, в чому ж перевага конкретної платформи, для вирішення
задачі пов’язаної з економією часу, та прибутковості справи? Чому
саме .NET і для чого інформація перед цим?
Для того, щоб відповісти на це питання, потрібно сформувати відповідь
на інше питання, що і буде відповіддю на це – що потрібно для сегменту
бізнесу нового покоління? Перевагою платформи, що буде використана для
проведення дослідження є те, що щоб задовольнити потреби бізнесу
необхідно, щоб новий розроблюваний додаток був не сильно затратний
відповідно до грошей замовника, а також надавав можливість розширення та
збільшення потужності.
1.2 Мова програмування C# та платформа .NET.
Ця мова програмування являється універсальною та займає своє
почесне місце майже в кожній комірці ІТ-бізнесу, якщо необхідно
реалізувати web-додатки або MVC – ASP .NET; якщо необхідно
програмувати кат-сцени для фільмів або розробляти ігри для більшості
платформ сучасності, наприклад Unity; якщо необхідно реалізовувати
комп’ютерні додатки – WPF [5]; реалізувати програмне забезпечення під
мобільні – Xamarin [6], що підтримує розробку для IOS та Android, а також як
і нативну розробку, так і реалізацію із спільним шаром програмного коду.
З новими версіями фреймворку з’являється можливість працювати для
вирішення задач, що будуть реалізовуватися майже під будь-яку платформу.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 9
А це означає, що фреймворк більш не є прив’язаним до продукції компанії
Microsoft. Також платформа постійно розвивається, оскільки з появою .NET
Core та повного злиття попередніх версій .NET Framework та злиття з Core в
версію .NET Framework 5, більшість функціоналу була взята з Open-Source.
Це означає, що покращення взяті від людей, що безпосередньо працюють з
даною платформою і пропонують свої рішення для тієї або іншої задачі.
Дослідивши вище сказана можна зробити висновок, що програмісти
використовують рішення, що були ними прийняті; що ці рішення є зручними,
оскільки саме вони є кінцевими користувачами для цієї мови та
використовують ті, або інші особливості даної мови програмування для
вирішення задач. По-третє, оскільки C# являється мовою, що компілюється, а
не інтерпретується, хоча і при використанні CLR, вона є набагато швидшою,
ніж мови, що розраховані на швидку розробку, але застосовують
інтерпретатори: Python, Ruby та ін.. Тому С# є тією мовою, яка задовольнить
умову швидкості розробки для макропроектів та збільшення їх можливостей.
1.3 Порівняльний аналіз мови програмування C# з іншими мовами
Для розробника на сьогоднішній день є дуже великий вибір
інструментів, і не можливість визначитися, яка саме мова програмування
являється найкращою і краще підходить під свою визначену задачу. Тому
необхідно обґрунтувати вибір мови C# для вирішення визначеної
проблематики і те, чому розробнику варто проявити інтерес саме до цієї
мови. Перше, що необхідно зазначити, що C# являється значно зручнішою,
ніж C++, швидшою в процесі розробки та найчастіше надає лише ті
можливості, що розробнику достатньо для вирішення необхідних задач.
Зважаючи на це на ринку ІТ все частіше виникає ситуація, коли для MVP
реалізують проект використовуючи C# та Java [7], а вже потім переписують
це на С++. До того ж сьогоднішня версія C# є значно швидшою мовою в
порівнянні з її прямим конкурентом Java, є різниця в швидкості обробки, те
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 10
наскільки було завантажено процесор; навантаженість процесора під час
роботі з алгоритмами. На рисунку 1.2 наведено порівняльний аналіз
швидкостей для C# та Java.
Рисунок 1.2 – Порівняня швидкостей сучасних версій C# та Java
До того ж платформа .NET розпочала розвиватись активно в сторону
активної спільноти, а тому в мови C# почала з’являтися велика кількість
прихильників. Однією з причин стало те, що вона більше не була прив’язана
до платформи .NET Framework, а також до старих стандартів.
З однієї сторони з’явилася можливість продовжувати далі конкурувати
з безпосереднім конкурентом Java в площі швидкості, але в розробників
даної мови програмування інші плани, наприклад, в gRPC більша швидкістьв
порівнянні з C++[8]. gRPC являється сучасною високопродуктивною
платформою RPC з відкритим кодом, що може працювати в будь-якому
середовищі. Вона може ефективно підключати послуги в центрах обробки
даних та між ними при допомозі підключенних сервісів виконувати
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 11
підтримку балансування навантаження, перевірки працездатності, трасування
та автентифікації. Дана технологія застосовується для розподілених
обчислень в процесі підключення пристроїв, мобільних додатків та браузерів
до серверних сервісів [8].
Також C# підтримує динамічне підключення інших програм та модулів
для отримування з них результатів, а це означає що, якщо в цій платформі
відсутні якісь модулі, то вона може запозичити це з інших ресурсів. Така
практика активно використовується під час розробки під WinForms із
залученням ОС Windows нативних бібліотек через C++.
Крім цього, C# один з небагатьох серверних мов на якій присутня
можливість розробляти клієнтську частину веб-сайту. Для клієнтської
частини можна розробляти як і компільований на сервері код, який тільки
потім віддає код клієнту, а зміни виконуються тільки за допомогою
спілкування з сервером напряму (RazorPages) або повноцінний SPA
фреймворк – Blazor.
Blazor[9] – це веб-фреймворк, що дозволяє відмовитись від JS повністю
і розробляти код лише на мові C#. На рисунку 1.3 наведено фреймворк
Blazor, що пропонує два рішень для клієнтської частини: ASP .NET
Corehosted, webassembly.
Різниця між підходамиз ASP .NET CoreHosted та WebAssembly [10] в
тому, що ASP .NET CoreHosted – це частково компільований код, що
спілкується з абстрактним сервером при допомозіSignalR,що
використовується для спілкування веб-сокетів, а це набагато швидше в
порівнянні зhttps. Недоліком даного підходу є необхідність наявності
постійного зв’язку з сервером, але клієнт при цьому не отримує логіки на
сервер.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 12
Рисунок 1.3 – Запропоновані рішення фреймворку Blazor
Інший варіантом є WebAssembly, що відрізняється тим, що на
клієнтську частину віддається частково зашифрований і обфускований весь
код, при цьому спілкування з сервером в нього виконується лише тоді, коли
необхідна будь-яка взаємодія з базою даних, або зовнішніми методами, які не
рекомендується, або немає можливості перенести на клієнт. Тобто саме
даний варіант підтримує рендеринг в реальному часу і дозволяє працювати
клієнтській частині, навіть без відсутності зв’язку з сервером. Працює цей
підхід так оскільки, виконуваний код компілюється в WebAssembly та
дозволяє працювати без JS.
WebAssembly є новим відкритим форматом байт-коду, який
виконується сучасними браузерами, дозволяє переносити код, що було
написано на наступних мовах C, C ++, C #, Rust в низькорівневіасемблерні
інструкції і використовувати його в мережі [11].
Оскільки даний формат з’явився лише в 2015 році, можна було б
очікувати, що він не підтримуватиметься більшістю браузерів, адже навіть
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 13
Flexbox, що зараз активно застосовується для верстування сторінок не може
забезпечити 100% підтримку для всіх сучасних користувачів.
Якщо говорити про Blazor [11], то це бібліотека, що активно
розвивається і досить суттєво впливає на спільноту. Вона дозволяє
розробляти додатки не лише для веб, а і розробляти мобільні додатки та
комп’ютерні версії, при цьому використовуючи одні і ті самі рішення
застосовані у вже готовому коді для реалізації інших рішеннях.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 14
РОЗДІЛ 2 АНАЛІЗ ІСНУЮЧИХ ПРОГРАМНИХ РІШЕНЬ ДЛЯ
ПЛАТФОРМИ .NET
2.1 Поняття репозиторію для платформи.NET
Всі рази, коли необхідно виконувати авторизацію або додавати дані до
певного профілю, клієнт має взаємодіяти з даними. На сьогоднішній день в
ІТ- технологіях дані переважно зберігаються на сервері або в хмарі, а саме в
SQL базах даних для маніпуляції цими даними необхідно знати SQL
(наприклад, MSSQL, MySQL, PostgreSQL, RavenDB тощо). Для такої
взаємодії користувачі розробники давно застосовують ORM. ORM - це шар,
що дозволяє користувачам взаємодіяти з базою даних застосовуючи
принципи ООП і при цьому не застосовуючи мову SQL безпосередньо.
Бібліотеки ORM розроблені для різних мов програмування. У
загальних випадках, технологія ORM надає можливість проектувати роботу з
даними за допомогою класів, а не таблиць даних. Дана технологія дозволяє
перетворювати класи в дані, що придатні для зберігання в базі даних, при
цьому схему перетворення визначає сам розробник. Також ORM дає простий
API- інтерфейс для CRUD-операцій над даними. Використання технології
ORM надає можливість не писати SQL-код для взаємодії з локальною базою
даних[10].
Переваги та недоліки технології ORM.
Переваги:
1) можливість оперувати елементами мови програмування, а саме:
об'єктами, класами, методами, атрибутами, а не працює з елементами
реляційної моделі даних;
2) існування явного опису схеми бази даних, що знаходиться і
редагується в одному місці та представлене в термінах для різних мов
програмування;
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 15
3) наявність можливості автоматичного створення SQL-запитів, що
позбавляє від необхідності використовувати мови для опису структури бази
даних (Data Definition Language) та мови маніпулювання даними (Data
Manipulation Language) в процесі проектування БД і заміні відповідної схеми;
4) вдосконалені реалізації ORM підтримують виведення успадкування
і композиції на таблиці;
5) немає необхідності створювати нові SQL-запити під час
перенесення на іншу систему управління базами даних, так як за ці дії
відповідає драйвер низького рівня ORM;
6) ORM надає можливість ізолювати код програми від подробиць
зберігання даних.
До недоліків можна віднести [10]:
1) додаткове навантаження на програміста, що заключається у
необхідності вивчення ORM, як «додаткового шару» між програмою та
базою даних, що також створює додатковий рівень абстракції, а саме, об'єкти
ORM. Дана проблема відома, як «impedancemismatch», а сама реалізація
ORM призводить до збільшення обсягу програмного коду та зниження
швидкості роботи програми. Але, з іншої сторони, ORM очно та в одному
місці концентрує відмінність між реляційною та об'єктно-орієнтованою
парадигмами, що не вважається недоліком;
2) помилки, що з’являються в програмі важко піддаються
налагодженню, якщо ці помилки присутні в реалізації ORM. Прикладом
може бути, помилка в реалізації кешування ORM, такі як узгодження змін
для різних сесій;
3) недоліки реалізацій, що можуть мати деякі обмеження і висувати
деякі вимоги. Прикладом може бути, вимога для власної схеми БД та
обмеження на засоби створення БД. Також може бути відсутньою
можливість створювати SQL-запити в явному вигляді.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 16
4) необхідна реалізація окремих таблиць у випадку прямого виведення
класів в таблиці.
Головним недоліком ORM є зниження продуктивності, причиною якої
полягає в тому, що більшість ORM направлена на обробку більшого об'єму
різноманітних сценаріїв використання даних. Для невеликих проектів, що не
працюють з високим навантаженням, застосування ORM є очевидним,
особливо у тих випадках коли важливим критерієм розробки є час.
2.2 Порівняння різних типів ORM платформи .NET
В стецітехнологійплатформи.NET для роботи з базами даних є три
основних лідери ORM: Dapper,Entity Framework Core та ADO .NET[12].
Для того, щоб виконати порівняння даних технологій та визначити
найбільш зручну ORM, що враховує критерій часу для певної реалізації,
необхідно написати SQL запити на вибірку та порівняти їх зручність в
процесі написання, підтримки цього коду, швидкості реалізації додаткових
модулів, швидкості реалізації готових рішень та швидкості виконання.
В першу чергу для прикладу необхідно створити таблицю бази даних,
відносно якої необхідно буде оперувати різними способами при допомозі
сформованих у майбутньому методів маніпуляції даними. На рисунку 2.1
наведено виглядати база даних для UML діаграмі.
Рисунок 2.1– UML діаграма для заданої таблиці БД
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 17
Щоб визначити працездатність кожної з досліджуваної системи
необхідно реалізувати код для тесту, застосовуючи який можна
проаналізувати працездатність коду, його місце в розробці фінального
продукту, а також зручність, зрозумілість та підтримуваність коду для
розробника. Для аналізу було реалізовано для кожної з обраних ORM три
вибірки за такими критеріями:
1. Гравці в команді.
2. Гравець за ідентифікатором.
3. Команди за видом спорту з включенням гравців.
Перш за все необхідно написати, яка взаємодія виконується з базою
даних, а саме, при використанні якого коду програми розробник має
можливість досягти вирішення описаних вище задач. А це означає, що
першим кроком необхідно описати рішення проблеми для даних бібліотек.
Першою було розглянуто взаємодію бази даних з бібліотекою Entity
Framework Core [13]:
1. Код програми для вибірки гравців відповідно до команди:
2. Код вибірки гравця за ідентифікатором:
3. Код для вибірки команди за ідентифікатором виду спорту
включаючи і гравців:
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 18
Наступними кроком є реалізація рішення застосовуючи ADO .NET[14]:
1. Вибірка гравців відповідно до команди:
2. Вибірка гравця за ідентифікатором:
3. Код для вибірки команди за ідентифікатором виду спорту
включаючи і гравців [15]:
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 19
Останнім були написані методи для Dapper [15]:
1. Для критерію вибірка гравців за командою код має наступний
вигляд:
2. Для критерію вибірка гравця за ідентифікатором має наступний
вигляд:
3. Для критерію вибірки команди відповідно до ідентифікатора
спорту включаючи гравців:
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 20
Дослідивши написані для різних ORM коди було визначено, що
найбільшзручним та найшвидшим для
розробкивиявивсясамеEntityFrameworkCore, оскільки для функціївибіркипід
час написаннябулореалізованомінімально коду, міграціїбулостворено за
допомогоюкомандиAdd-Migration та дана бібліотекане
потребуютьвикористаннядодатковихпакетів, як іншібібліотеки. Розробник не
застосовував код SQL безпосередньо, а використовувавлишемову C#. А
цеозначає, що в майбутньому, якщоіншомурозробникунеобхідно буде
виправити ту, абоіншуділянку кодуто це займе у ньогоменше часу, і при
цьому будезнижуватися іціна самого спеціаліста при розробці.
Отриманіпоказникиактуальнілишевідносношвидкостірозробки. Для
визначенняшвидкостіобробкицихбібліотекбуловиконано10 запусків та
проаналізованоотриманісереднізначення для кожної з цихбібліотек.
Результативиконаннянаведено в секундах.
Для бібліотекиADO .NET результатом є 0,013 для
критеріювибіркигравцязайогоідентифікатором; 1.03 мс за
критеріємвибіркигравцівкоманди та 8.84 для критеріювибіркиусіхгравців та
команд заназвою спорту.
Для бібліотекиDapperрезультатинаступні: 0,047 для
критеріювибіркигравцязайогоідентифікатором; 1.01 мс для
вибіркигравцівкоманди; 7.94 для критеріювибіркиусіхгравців та команд
заназвою спорту.
Для бібліотекиEntityFrameworkCore результатом є значення 0,77 мс
відповідаєкритеріюдля вибіркигравцязайогоідентифікатором; 3.57 мс
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 21
значеннядля вибіркигравцівкоманди; 113.45 значеннядля вибіркиусіхгравців
та команд заназвою спорту.
Для того,
щоботриматибільшнагляднурізницюміжреалізаціямибібліотеквідносновизнач
енихкритеріївбулопобудованодекількаграфіківрезультати для яких наведено
на рисунках 2.2 -2.4.
Рисунок 2.2 – Критерійвибіркигравця за його ідентифікатором
Рисунок 2.3 – Критерій вибірки гравців за їх командою
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 22
Рисунок 2.4 – Критерій вибірки команд та гравців по ідентифікатору
відповідно до назви спорту
Дослідившиотриманірезультатибуловизначено,
щобібліотекаEntityFrameworkCore показала себе не дужеефективноюв
процесіроботи.Але вона являєтьсянабагатокращою для реалізаціїбізнес-
логіки в майбутньому, аніжінші ORM. По-перше час розробки для
даноїбібліотеканайкращий, оскільки в майбутньому не буде
необхідностіпереписуватибагато коду, а надасть говорить про те,
щообсягпереписаного кодунабагатоменший, в порівнянні з тим,якщо
будевикористано для вирішенняцієїабоіншоїзадачііншушвидку мову з
інтерпретатором. Тобто, ценадаєможливістьрозробникуматиготовий MVP,
якийбудутьвикористовуватикористувачітаприноситимінімальнийдохід. Ще
одним позитивним моментом є те, що у
випадкувикористовуванняEntityFrameworkCoreрозробникунемаєнеобхідності
прив’язуватись до конкретноїбазиданих, а цеозначає, щоколи проектбуде
змінено з MySQL до PostgreSQL при цьомузмінибудутьмінімальними, тобто,
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 23
все щонеобхіднозмінити – це провайдера, якийінкапсулює всю роботу з
базами даних і робить все за розробника. Тобтоу випадку, якщоце все буде
написанопідDapper, ADO .NET проблема, яка можевиникнутибуде в тому,
що все, щовідміннеміжцимидвома базами даних, а інодіі версіями,
необхіднопереписувати всю логіку, яка зав’язана на цьому.
Дослідившиотриманівищерезультатибулообрано
длявикористовуватисаметехнологіїEntityFrameworkCore для того,
щоббуламожливістьнаписатидешевий, а такожробочийваріант MVP, оскільки
для того, щобкористувачякосьвідчуврізницюміжзапитами, необхідномістити
велику кількістьіншихкористувачіві при цьому велику навантаженість.
2.3 БазовалогікатехнологіїEntityFrameworkCore
Для того, щобматиможливістьвзаємодіяти з базою
данихнеобхідностворити та ініціалізувати в контейнері DI йогоекземпляр.
DependencyInjectionContainer (DI Container) або контейнер
впровадженнязалежностей– цепатерндля проектування, сутьякогополягаєв
тому, щобвирішитивсізалежності, щоіснують у об'єкта при йогостворенні.
Цеможназробитивикликавши в класіStartup в
методіConfigureServicesфункціюservices.AddDbContext<MainDbContext>, де
MainDbContext – цеклас, що є нащадкомвідкласуDbContext, а такожв
ньомуописанівсітаблиці, зв’язкиміжтаблицями та ін.
Тобтовиконуватикерування самою базою даних. Післявиконанихкроків, у
випадку колирозробникунеобхідновиконативзаємодію з базою даних,
йомунеобхідновикликати в контролеріабосервісі конструктор і
передатиоб’єктцьогокласуяк параметр. Як
результат,об’єктповністюдоступний для опрацьовування базою даних[12].
Щобзрозумітибазовулогіку і те, як рекомендує з
цимпрацюватикомпанія Microsoft, необхіднорозглянутикожнийз
етапівокремо, і відповіднозробитивисновкивідповідно до досліджень.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 24
Такожнеобхідновраховувати, щокоженіззапитівможнаотримати в SQL типі,
що в майбутньомуполегшитьпереписування коду на більшпродуктивний, але
при цьомунеобхідно, при ініціалізації контексту класу в класіStartup, під час
передачі до цьогооб’єктуопційдодатиEnableSensitiveDataLogging.Післяцього
кроку, у випадку, якщо в проекті включено веденнялогівпридопомозіSerilog,
Nlogта ін., з’являєтьсяможливимотриматитрансльований запит SQL,
щонадсилається до SQL сервера. Реалізаціюданоїможливості наведено на
рисунку 2.5.
Рисунок 2.5 – Трансльований код при використанні технології
EntityFrameworkCore з мови C# в SQL запит
Першим крокомбулорозглянуто метод створенняелементу,
щозберігатиметься в таблиці. Щобзберегти в таблицідані,
необхідноспочаткуотриматиоб’єктданих, класдля якогоспоріднений з
визначеною таблицею та зв’язанийпридопомозіміграцій. Далівикликати
контекст та звернення до його поля, щопов’язане з таблицею. Наступним
кроком необхідновикликати метод Add та передати в ньогооб’єкт,
щопотрібнододативтаблицю. Після того, колиоб’єктбуло додано, він не
переданийще в базу данихбезпосередньо, а закешованимзберігається
локально, щобпри цьомуне навантажувати сервер і зберігатиоб’єктлише при
необхідності. Щобзберегтинаявний стан
знімкубазиданихнеобхідновикликати метод SaveChanges,
вякомунаявнийасинхронний метод, щобвиконувати код в асинхронному
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 25
потоці. Після того, як метод для зберіганнябуловикликано буде
виконановалідаціюданих, іу випадку, якщовсіданівалідні данийоб’єкт буде
збережено.
Для того, щоботриматиоб’єкт з базиданихіснуєдекількаметодів, тому
розглянемодля прикладуїхвсі[14]:
1. FirstOrDefault – метод, щоприймає в собі предикат та повертає
перший об’єкт, щобулознайдено по заданому та переданому предикату. У
випадку, якщозначення не булознайдено буде повернено як результат
екземпляр, щостворений методом default (за замовчуванням).
2. Find – метод, щошукає за індексованими полями, наприклад,
виконуєтьсяпошуклише за ідентифікатор та повертаєзначення при
першомузнайденомуспівпадаючомузначенні.
3. Where – метод, щоприймає в собі предикатта повертає список
елементів, щозадовольняють даний предикат.
4. SingleOrDefault – метод, щоприймає в собі предикат. Відмінністьвід
методу FirstOrDefault в тому, що при
знайденомупершомуспівпадінніелементапошук буде продовжено, а при
знаходженні, ще одного елементу буде виведенопомилку.
Розрізняютьнаступні типи запитів:відстежуванні і невідстежуванні. За
замовчуваннямвсізапити, щоповертаютьоб'єктикласів моделей є
відстежувати. В процесіотримання контекстомданих з базиданихEntity
Framework поміщаєвилученіоб'єкти в кеш і відстежуєзміни, щовідбуваються
з данимиоб'єктами аж до застосування методу SaveChanges () /
SaveChangesAsync (), щофіксуєвсізміни в базіданих. Але такідії не завждиє
необхідними[15] (наприклад, у випадкуколи необхідно просто
вивестиданідля перегляду).
Для того, щобдані не поміщати в кешвикористовується метод
AsNoTracking() або ж в тілі конструктору контексту замінюємо стан
ChangeTracker на значенняfalse. Даний метод застосовуєтьсядо
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 26
наборуIQueryable. При йогозастосуваннідані, щоповертаютьсяіззапиту не
кешуються. Тобто запит є невідстежуваним.
Такі ж самі кроки можнавиконати для випадку,
коливитягуєтьсяекземпляр з об’єкту, необхідновикликати метод у
контекстіEntry та в результатінеобхіднозвернутися до поля State
тазмінитийого стан на Detached. Післяданихкроківзакешованіданібуде
змінено і данийоб’єктбільше не трасується.А цеозначає, щоEntity Framework
не виконуєдодатковуобробку і не виділяє при цьомудодатковемісце для
зберіганнявилучених з базиданихоб'єктів, а тому
такізапитипрацюютьшвидше.
Щоб виконати оновлення об’єктуіснує декілька способів: додавання
об’єкту в метод Update, зміни для якого мають зберігатися локально в
контексті даних. Потімнеобхідно викликати метод SaveChangesAsync,
важливо пам’ятати, що об’єкт зберігається повністю, а це значить, що ті
поля, що були спустошенні видаляються на сервері.Для часткового
оновлення метод існує два способи: 1. необхідно викликати метод Attach в
контексті, важливим є наявність ідентифікатора відносно якого
необхідновиконати дії відповідно до зміни деяких полів, потім необхідно
викликати в контексті метод Entryі передати в нього об'єкт, що
булозакешовано та викликати метод Propertyпередавши в ньогоназву
параметру, щонеобхідно змінити, а в кінці змінити значення поля IsModified
на значення trueта зберегти його за допомогою методу SaveChanges[12].
Другий спосіб це використанняJSONPatchDocument. Першим кроком
буде створення простого класу DTO, відносно нашого об’єкту.
DataTransferObject (DTO) являється одим з шаблонів проектування, що
використовується для передачі даних між підсистемами додатку.
DataTransferObject, на противагуbusinessobject або dataaccessobject не має
містити жодну описану логіку або поведінку. Тепер в методі контролера
необхідно зазначити, що буде отримано не просто елемент типу DTO, а що
він являєтьсятипомGeneric для JsonPatchDocument. Далі після того, як даний
об’єкт було передано в метод контролера необхідно викликати для цього
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 27
методуapply, а далі викликати метод, що зберігає дані в контексті даних.
Важливо знати, що якщо об’єкт буловідтрасовано і після цього було
виконано якісь зміни, то контекст викликає помилку, яка вказує, що такий
об’єкт з таким ключом вже закешований і що він не підлягає зміні [10].
У випадку видалення об’єктунеобхідно викликати у об’єкта контексту
даних метод Removeі передати як параметр сутність, що необхідно видалити,
а потім викликати метод для збереження даних у контексті.
Щоб виконати сортування за конкретним полем необхідно викликати в
колекції, що є нащадком інтерфейсуIQueryble метод OrderBy та передати
назву поля по якому будемо виконуватися пошук (передача по його типу).
Потім необхідно передати параметр типу Boolean, що буде відповідати за те,
як необхідно провести сортування – за спаданням або зростанням. Дану
операцію необхідно робити саме з інтерфейсом IQueryble, оскількидоки
даний список знаходиться в даному інтерфейсі даних виконується
оперування з даними SQL, а не з вилученими даними, і лише під час
конвертації в інший тип списку запит буде переслано в БД і буде вилучено
всі дані, що задовольняють даний запит [13].
Щоб визначити різницю між даними запитамибуло виконано тестовий
запит в базу даних, один залишився з інтерфейсом IQueryble, а інший відразу
після отримання результату застосовуючи мето ToListAsync було
конвертовано в List. Результати отримані під час тестового запиту наведено
на рисунку 2.6.
В процесі виконання даної роботи було визначено, що в другому
випадку, коли застосовувавсяList було отримано всі задовільні результати
для пошукового об’єкту, але при цьому, всі наступні дії оперують вже з
об’єктами, що в свою чергу, навантажує саму систему. На рисунка 2.7
авантаженість на ресурси комп’ютера під час маніпуляції даними з
використанням інтерфейсу колекції List.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 28
Рисунок 2.6 – Визначені результати під часконвертації об’єктів з бази
данних в об’єкт типу List
Рисунок 2.7 – Навантажуваність на ресурси комп’ютера під час
маніпуляції даними за допомогою інтерфейсу колекції List
На рисунку 2.8 наведено, що IQueryable не повертає готових даних
користувачу до моменту колиданий запит не буде викликано конвертацією в
інший елементабо повернено цей елемент в клієнт з серверу. А відповідно до
рисунка 2.9 можна зробити висновок, що інтерфейс IQueryable є менш
затратним порівняно з List.
Як видно з результатів тестування, що навіть при маленькій кількості
елементів, в масиві було всього 40 об’єктів типу «String», різниця була
відчутна і склала всього 9.3 мб, при цьому такий же запит з Listвже важив
148.4мб, а запит з IQueryable – 139.1 мб . А це говорить про те, що якщо б це
були, наприклад, дані користувача, які б підключали лише декілька
внутрішніх полів, то ця б різниця була набагато більшою.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 29
Рисунок 2.8 – Отримані результати під часконвертації об’єктів з бази даних в
об’єкт типу IQueryable
Рисунок 2.9 – Навантажуваність на ресурси комп’ютера під час маніпуляції
даними в процесі використання інтерфейсу колекціїIQueryable
Томунеобхідно брати до уваги той факт, що цей запит навантажує не
пам’ять комп’ютера, а пам’ять серверу SQL, то даний запит більш вигідний
для бізнесу, оскільки більшість сервісів, що займаєзначну нішу в серверному
бізнесу, а саме: Amazon, DigitalOcean, Azure мають на продажі сервіси, що
орієнтовані на продаж серверів тільки з базами данних, що вже оптимізовані
та скомплектовані найкращим чином.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 30
РОЗДІЛ 3ПРОГРАМНЕ ВДОСКОНАЛЕННЯ ІСНУЮЧИХМЕТОДІВ
ТА ПАТЕРНІВ РОЗРОБЛЕНИХ НА БАЗІ ПЛАТФОРМИ .NET
Щобвирішитиіснуючіпроблеми: швидкостірозробкиновихсервісів,
зручністьпрограміста на стороніклієнта,підтримка та розширеннядодатків,
булорозроблено та запропонованотакіалгоритми.
3.1 Сортування та фільтрація для вдосконаленняметодів
ІснуючарозробкаEntityFrameworkCoreпропонуєпередавати, як параметр
для сортуванняназви поля за
допомогоюякогонеобхідновиконуватисортування в якостійого типу.А
цеозначає, щобвиконалосясортуваннянеобхідновикликати в списку, що є
нащадкомIQueryable метод OrderBy, щоприймає в собітільки типи
Expressionта Function.Це значить, що для того, щоброзробитинові типи,
розробникунеобхіднобулонаписатиновуреалізацію,
тобтонаписатидлякожноїназвиумови переходу,
наприклад,if(a=”Name”){list.OrderBy(m=>m.Name}, а у випадку,
якщоконструкцій, щорозглядаються, буде декілька і використовуванихполів
за якимирозробникунеобхідносортувати буде за 30 або 40 рядків. У випадку,
якщо проект матимевеликийрозмір, то
йогорозробказвичайногосортуванняможезайняти не одну годину, а
декількатижні.
Щобспроститиреалізаціюваріанту, щорозглядаєтьсята
покращитийогобулорозробленонаступний алгоритмдій.
Спочаткунеобхідноотримативідклієнтаназву поля за яким, буде
виконаносортування. ПотімстворитистатичнийкласQueryableExtensions, для
того, щобвикликатицей метод і не створюватипри цьомудодатковіоб’єкти,
потімнеобхідностворити метод, який буде повертативідсортуваний список
елементів типу TEntity таприймати три параметри
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 31
–thisIQueryable<TEntity>query, тобто, тіло списку
відносноякогонеобхідновиконатисортування; другим параметром
являєтьсяназва поля використовуючи яку буде проводеносортування типу
string;третійпараметр визначає, як самебуде виконуватисясортування за
спаданнямабо за зростанням.
Наступноюдієюнеобхідно в тілі методу використовуючи метод
typeofвизначити тип класу шляхом передачі в якості аргументу поляоб’єкту.
Післяцьогодля отриманого типунеобхідновикликати метод
GetPropertyтапередатидо методуназву поля за якою буде
виконуватисясортування. Вжепісляотриманняоб’єкту з поля
необхідновикористовуючиклас та йогостатичний метод Expressionстворити
сам параметр для Expression.
Щобвиконатиданідіїнеобхіднойоговикликатитапередатиуякостіпараметрів
тип об’єкту, щобувотриманийраніше.
Післявиконанихдій, наступним крокомпотрібнонадати доступ з цього
параметру до поля,щобулопроініціалізованораніше.Щобнадати доступ
необхідно у класіExpressionвикликати метод MakeMemberAccess та
передативнього два параметри: перший об’єкт– типу ParameterExpression, а
другий параметр – типу PropertyInfo. Наступним кроком є створення
лямбдафункції, яку можна буде передати в контекст для
виконаннятапередаємо до неїоб’єкт поля, та яка використовується для
зв’язку з класомвідносноякогобуввиконанийзв’язок.
Післявиконанихдійпотрібнопроініціалізувативикликствореного методу, але
для цьогонеобхідно в класіExpressionвиконативиклик методу Call
передаючив ньогонаступніпараметри – typeof(Queryable),
щовикористовуєтьсядля створенняоголошення списку відносноякого буде
виконуватисясортування, наступним крокомнеобхіднопередатитернарний
оператор умови, що буде викликатися в залежностівід того, яке
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 32
самезначеннябуде передано для сортування, у випадку, якщоцеtrue, то буде
викликано метод Order By, інакше методOrderByDescending.
Післявиконанихдійнеобхіднопередатимасив типу Type
іпередатийогоізпроініціалізованимиелементами, а саме: типом,
щобулоотриманона самому початку, а другийелемент євнутрішнім поле в
проініціалізованомуранішеPropertyInfoта
маєзначенняPropertyType.Наступноюдією є передача в даний метод дерева
виразів з елементів спискувідносноякого буде виконуватисясортування, а
останнім параметром є результат виконання методу QuoteкласуExpression та
передана в ньогофункція лямбда.
Післявиконанихдійбулоотримано результат типу MethodCallExpression,
щоявляєтьсямайжестворенимвикликом того виразу,
щобувреалізованийраніше. Наступним кроком необхідновикликатистворений
тип у списку за допомогою, якого буде проводитисьсортування. Для
цьогонеобхідновикликати у цьому списку поле провайдер і потімзцього поля
необхідновикликати метод CreateQuery, в якомуузагальненим типом
являється то й самий тип, що і в самому спискувідповідно до
якоговиконуєтьсясортуваннята передати в ньогооб’єкт типу
MethodCallExpression, щобулоотриманораніше.
На рисунку 3.1 наведено код програми для описаноговище алгоритму
покращенняEntityFrameworkCore.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 33
Рисунок 3.1 – Код програмиописаноговище алгоритму
Зараз коли необхідно провести сортування відносно конкретного поля,
немає потреби писати багато конструкцій з умовними переходами, а
необхідно лише викликати у Queryable метод OrderBy та просто передати в
нього тип generic, з яким потім будуть проводитись операції, а в тіло виклику
методу передавати назву поля і параметр типу boolean, щоб сервіс визначав,
який тип сортування обирати – за спаданням або зростанням.
Тобто, це означає, щочас написання коду сортування для кожного
наступного сервісу відповідно до конкретної сутності падає в рази,при цьому
сервіс стає більш простим і зрозумілим для розробника, а більша частина
коду ховається поза межіогляду розробника.
Для подальшого дослідженнянеобхідно визначити різницю між
стандартним та модифікованим методами, визначити впала чи зросла
продуктивність відповідно до базового виклику методу OrderBy, а також
передбачена можливість використання нових методів.
На рисунку 3.2наведено результати роботи нового модифікованого
методу. Як видно з результатів модифікований метод в середньому працює
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 34
на 10мс повільніше ніжстандартний метод, але дає більший приріст в
швидкості розробки додатків і дана похибка являється задовільноюв процесі
розробки MVP продукту.
3.2 Часткове оновлення сутностей в процесі модернізації методів
Щоб вирішення дану проблему необхідно написати метод, що буде
розширювати методи класу. В подальшому було розроблено статичний клас
EntityExtensions, для того, щоб була можливість викликати даний метод і не
реалізовувати при цьому додаткові об’єкти, наступним кроком необхідно
створити новий статичний метод, що буде повертати елементи типу TEntity
та приймати в себе два параметри типу T, де першим параметром є об’єкт,
який було отримано з бази, а другий - об’єкт, що буде оновлено.
Рисунок 3.2–Визначені результати при використанні IQueryable
Перше, що необхідно зробити це отримати з об’єкту, що оновлюється
тип за допомогою методу GetType, далі потрібно
використовуючиGetProperties отримати всі необхідні поля і застосовуючи
цикл foreach отримати елемент поля зі списку полів.Далі в отриманих
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 35
поляхнеобхіднопорівняти ім’я та Idі визначити чи вони не є рівним. У
випадку, якщо дані параметри не рівні, необхідно отримати тип цього
поля.Коли об’єкт типу поля було отримано, необхідно отримати його тип:
значимий аболінкований типи. У випадкуколи тип є значимий необхідно для
нього створити стандартне значення використовуючи класActivator та його
статичний метод CreateInstance, куди передаєтьсяотриманий типзначення. У
випадку, якщо типлінкований необхідно отримати типnull, для якого
необхіднопорівняти значення, що було отримано з поля об’єкту,
щонеобхідно оновити зі значенням, яке було отримано перед цим. Якщо
порівнюванні значення не рівні потрібно викликати в об’єкта, який було
отримано з бази та викликати в ньому метод GetType.Далі коли отримано
результат необхідно викликати методGetProperty передати в нього ім’я поля
та оновити значення методувикористовуючи метод SetValue та повернути
об’єкт на оновлення.
На рисунку 3.3 наведено текст коду описаного алгоритму для
реалізації.
Рисунок 3.3 – Код описаного алгоритму
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 36
В процесі проведення експерименту було визначено, що розглянутий
методможна ще покращити. В побудованому алгоритмі поле являється дуже
залежним від об’єкту і йогонеобхідно отримувати з бази даних. Це означає,
для того, щоб оновити об’єкт частково розробнику необхідно робити зайвий
запит в базу даних, щоб отримати об’єкт. Основуючись на даних результатах
було прийнято рішення розробити спосіб, що буде модифікувати
модифікований метод та дозволить мінімізувати навантаження.
Для того, щоб вирішити визначену проблему та розробити алгоритм
необхіднорозробити метод, який розширює методи класу. Першим кроком
було додавання до розробленого в попередньому варіанті алгоритму
статичний клас EntityExtensions, для того, щоб була можливість викликати
даний метод при цьому не створюючи додаткові об’єкти. Далінеобхідно
створити новий статичний метод для якого типом повернення буде тип void,
тобто метод нічого не повертатиме, але прийматиме два параметри: перший
параметр являється контекстом бази даних, другий параметр є об’єктом,
щонеобхідно оновити оновленим об’єктом, для якого з обов’язкових полів є
лише Id.
Першочерговонеобхідно за допомогою контексту додати в кеш даний
об’єкт. Дану задачу можна виконати просто звернувшись до об’єкту
контексту і викликавши в нього метод Attach та передавшиу виклик методу
об’єкт. Після цього необхідно отримати з об’єкту, що оновлюється, тип
використовуючи метод GetType, а потім за допомогою методу GetPropertiesта
циклу foreach отримати всі необхідні поля.Після того, як було отримано
полянеобхіднопорівняти чи ім’я поля не є рівним Id.У випадку, якщо
значення не є рівним, то необхідно отримати значення з цього поля
викликавшизнього метод GetValue. Після того, коли значення буде отримано,
необхідно порівняти чи воно не є пустим. У випадку, якщо воно не є пустим,
то потрібно викликати з контексту метод Entry та передати в нього об’єкт,
який необхідно оновити. Наступним кроком необхідно викликати метод
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 37
Property для того, щоб визначити, яке саме поле необхідно оновлювати,та
передати туди значення поля Name. Після виконаних налаштувань потрібно
звернутись до поля IsModified та змінити його значення на true. Після
закінчення циклунеобхідно у контексті викликати метод SaveChanges().
Фінальний код модифікованого методу, який має наступний вигляд, як
наведено на рисунку 3.4.
До негативних сторін розробленого методу відноситься те, що якщо
параметрами будуть об’єкти, які є вкладеними, такі об’єкти не зможуть бути
оновленими, але такі випадки, коли необхідно оновлювати вкладені об’єкти
дуже рідкісні.
Рисунок 3.4 – Фінальний код модифікованого методу
Крім визначеного вище недоліку реалізований метод є занадто
прив’язаний до контексту даних, а це значить, що об’єкт повинен виконати
всі зміни до оновлення, інакше, у випадку, коли метод для зберігання бази
даних не буде викликатись, це призведе до маси проблем, оскільки об’єкт
продовжуватиме бути закешованим і у випадку іншого запиту для
збереження файлу з ідентичним ідентифікатором можуть виникнути
помилки.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 38
У випадку, коли всі можливі проблеми були визначено необхідно знову
порівняти швидкість працюючих трьох способів оновлення. Для цього
необхідно запустити 10 раз кожен зі способів досліджених в процесі
експерименту та виконати заміри.
В ході проведення експерименту було виявлено, що останній
проведений методмінімально відрізняє в продуктивності від стандартного, у
порівнянніз методом в якому необхідно було брати оригінал сутності перед
тим, як буде оновлено базу даних. Середнє отримане значення не
модифікованого методу рівне 1.3; середнє значення модифікованого методу
за допомогою вибірки з бази даних – 2.5; середнє значення модифікованого
методу при застосуванні контексту і кешуваннярівне 1.35.
Результати роботи методів отриманих в процесі експерименту наведено
на рисунку 3.5.
Рисунок 3.5 – Отримані в процесі експерименту результати роботи
методів за допомогою IQueryable
3.3 Вдосконалення методів універсального репозиторію
Наступна проблема являється проблема повторюваності коду під час
роботі з базою даних. Дуже часто під час реалізації проектів є маса
повторюваного коду, тобто однакові частини коду зустрічається як і в
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 39
процесі створення, так і в процесі отримання та оновлення об’єкту, у
випадку, якщо це просто додавання без будь-яких змін, то під час
перезаписування даних змін майже нічого не зміниться, але у випадку, якщо
є так зване м’яке видалення або відслідковування дати оновлення або
додавання і т.д., то при перезаписуванні або дослідженні цього коду
необхідно витратити багато часу. Тому для того, щоб вирішити визначені
проблеми було запропоновано наступні дії.
В першу чергунеобхіднорозробити базовий інтерфейс від якого
необхідно буде унаслідуватись іншим сервісам. Даний крок необхідний для
того, щоб підписати всі існуючі сервіси на конкретний контракт і для
випадку, щоб проект забезпечував ідентичність між сервісами для зручності
його застосування. Щоб реалізувати даний інтерфейс рекомендуються
виконати наступні дії:
 необхідно прописати інтерфейс який вміщуватиме його назву та його
узагальнені типи, для конкретного випадку – це публічний інтерфейс, що
містить в собі узагальнені типи T, TFilter,TKey, де Т являється сутністю з
якою буде працювати сервіс, TFilterє фільтром за допомогою якого буде
реалізовуватись фільтрація,а TKey – це його первинний ключ. До того ж
необхідно зазначити, що T являється класом, а TFilter є нащадком
класуFilterBase.
FilterBase – це клас, що не містить ніякої логіки реалізованої всередині
класу, але вміщує в собі три поля – типу longId, orderBy типу string, щоб
отримувати значення за яким виконуватиметься сортування та
OrderByDescending типу bool, що надає розуміння того, який тип сортування
необхідно виконувати за спаданням або зростанням.
Щоб реалізувати контракт необхідно застосувати наступні методи:
 декілька реалізацій Get, що буде повертати об’єкт типу Т та
приймати значення ключа для виконання пошуку за ключе;
 Get, що буде повертати IEnumerable<T>, щоб отримати всі елементи;
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 40
 Get, що буде повертати об’єкти типу PagedResponse, що зберігає в
собі два поля: список елементів типу Т та поле типу PageInfo, що зберігає в
собі поточну сторінку, кількість елементівта кількість елементів на сторінці.
Даний метод приймає об’єкт типу PageInfo, для можливості здійснювати
пагінацію під час вибору елементів;
 Get, що буде повертати об’єкти типу PagedResponse і приймати, крім
PageInfo, об’єкт,щоявляється нащадком класу FilterBase для
можливостівиконувати фільтрацію;
 додати методи для оновлення та повернення типу T, щояк
параметри, приймає в себе ключ TKeyі саму сутність типу T. Щоб
реалізовувати функцію додавання метод має повертати тип T та приймати в
собі сутність типу T, а для видалення – метод, повертає результат в значені
типу bool та приймає в собі аргументом ключ для видалення типу TKey.
На рисунку 3.6 наведено код програми для реалізації вищенаведеного
алгоритму.
Рисунок 3.6 – Код програми реалізації базового інтерфейсу від якого
необхідно буде унаслідуватись іншим сервісам
Наступним кроком буде розробка сервісу під реалізований інтерфейс.
Перш за все необхідно створити клас під назвою ServiceBaseдля
якогонеобхідно створити поле контексту і через конструктор
проініціалізувати об’єкт для нього. Наступним кроком необхідно створити
метод та додати для нього модифікатор virtual. Дану процедуру необхідно
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 41
виконувати всіх наступних методів, для того, щоб мати можливість
переписувати або модифікувати той чи інший метод, що не буде
задовольняти систему та її потреби. Першим методом, що було реалізовано є
метод GetQueryable, що повертав значення IQueryable<TEntity>.Даний метод
відповідає за те, щоб в будь-який момент була можливість отримати список
елементів визначеного типу з бази даних та можливість оперувати цими
даними. Це можна зробити викликавши в об’єкт-контекст метод Set, що
містить в собі клас узагальненого типу TEntityі повернути значення, як
результат виконання методу AsNoTracking, з цього методу для того, щоб не
виникало конфліктів в майбутньому серед вилучених значень з таблиці.
На рисунку 3.7 наведено код програми розробки сервісу під
реалізований інтерфейс.
Рисунок 3.7 – Код програми розробки сервісу під реалізований
інтерфейс
Наступний метод для вдосконалення це метод Get, що повертає
значення в типі Task<IEnumerable<TEntity>>, де Taskвизначає операція, що
розглядається виконана в асинхронному потоці, значення IEnumerable, що
користувач як результат отримає готовий список, що являється нащадком
інтерфейсу IEnumerable, а параметрTEntityвизначає тип об’єктів, що
містяться в колекції. Щоб виконати дані налаштування, необхідно викликати
вже розроблений метод GetQueryable та викликати з нього метод
ToListAsync. До методу ToListAsync необхідно застосувати операнд await для
можливості синхронної операції спостерігати за виконуванням асинхронної
операції, а по закінченню могла повернути значення з бази даних.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 42
На рисунку 3.8 наведено код блоку для типу
Task<IEnumerable<TEntity>>.
Рисунок 3.8 – Код програми для типуTask<IEnumerable<TEntity>>
Наступний метод, що буде вдосконалено є методGet, що повертає
інший тип, а саме,Task<PagedResponse<TEntity>та передає в тіло виклику
данного методу об’єкт типу PageInfo.Робота даного методу заключається в
наступному:необхідно з колекціїGetQueryable, щоявляється нащадком
ІQueryable, далі викликати відповідно цієї колекції метод OrderBy та вказати,
що цю колекцію буде відсортовано по ідентифікатору, для випадку, якщо
таблиця буде індексуватися іншим способом.Наступним кроком до
результату необхідно викликати метод Paginate та вбудувати в його виклик
об’єкт PageInfo.Реалізацію методу Paginateнаведено в додатку Б.
На рисунку 3.9 наведено реалізацію методу
Task<PagedResponse<TEntity> .
Рисунок 3.9 – Реалізацію методу Task<PagedResponse<TEntity> .
Наступний, що необхідно додати – це метод, який буде вилучати об’єкт
з бази даних за його ідентифікатором.Для цього необхідно визначити метод з
наступною сигнатурою:метод буде повертати об’єкт типу Task<TEntity>, в
тілі виклику методу буде мати ідентифікатор TKey.Наступним кроком,
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 43
необхідно викликати метод GetQueryable, отримавши результат викликати в
нього метод FirstOrDefaultAsync та передати до нього лямбду функцію, що
виступатиме предикатом для зрівняння ключів об’єктів, як результат
необхідно повернути об’єкт. Крім цього необхідно зазначити, що можна
викликати замість FirstOrDefaultAsync методу Find, що шукатиме швидше,
оскільки він застосовується лише для пошуку індексованих полів. Але для
даної задачі його використання не є можливим, оскільки метод Find
викликається лише відносно методу DbSet, а екземпляр такого класу
неможливо повернути з бази даних. Також для даної реалізації методу
замість порівняння з використанням символів рівності «==» було
застосованопорівняння за допомогою методу Equals. Це обґрунтовується тим,
що ключі можуть мати різну форму та їх ідентичність може виражатися по-
різному відносно від розробленої системи.
На рисунку 3.10 наведено код реалізації досліджуваного методу.
Рисунок 3.10 – Код програми для методу, який буде вилучати об’єкт з
бази даних за його ідентифікатором
Перед тим, як приступити до реалізації методу, що буде створювати
об’єкти, необхідно створити два методи BeforeCreate та AfterCreate, які
застосовуватимуться для того, щоб не потрібно було переписувати всю
ділянку коду відносно створеного методу та мінорні зміни з відносним
станом перед створенням, а після створення не впливали на саме створення
об’єкту.Щоб уникнути таких впливів методи повинні вміщувати наступні
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 44
параметри:BeforeCreateнеобхідно повертати об’єкт типу TEntity та
отримувати об’єкт типу TEntity і не виконувати ніяких обчислювальних дій
відносно сутності в базовій реалізації.
На рисунку 3.11 наведено код програми для створення методу
BeforeCreate.
Рисунок 3.11 – Код програми створення методу BeforeCreate
Далі необхідно створити метод для логіки, що буде застосована після
створення об’єкту. Даний методпрацює наступним чином: він нічого не
повертає (має тип void) та приймає в себе лише один елемент типу TEntity.
На рисунку 3.12 наведено вигляд методу AfterCreate.
Рисунок 3.12 – Вигляд методу AfterCreate
Після реалізації цих методів є можливим створення методу для
створення самого об’єкту. Даний об’єктмає наступну сигнатуру: повертає
методу об’єкт типу Task<TEntity> та приймає значення об’єкту типу TEntity.
Перш за все необхідно перевіритичи не є переданий тип пустим, у випадку
якщо він пустий, то необхідно відразу його повернути без створення цього
об’єкту. Наступним кроком необхідно викликати у класі контекст
методуBeginTransaction для того, щоб будь-які зміни, що були виконані під
час хоча б одного сценарію, що задовольняє умови розробника, не
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 45
торкнулися бази даних. Як результат необхідно отримати модифікований
об’єкт, за допомогою реалізованого розробником методу BeforeCreate, а
також його поточну реалізацію відносно поточного сервісу. Наступним
кроком необхідно викликати у контексті метод Add та передати в нього
об’єкт, що повинен бути доданим в базу даних. Даний метод повертає
значенняEntityEntry,яке як результатнеобхідно зберегти в змінній.Після того,
як було викликано метод в контекстіSaveChangesAsync, об’єкт було
оновленовідповідно до вимог описаної бази даних. Наступним кроком буде
змінав поле State цього об’єкту та оновлення його значенням Detached, яке є
одним з варіантів entity під назвою EntityState. Далі у контексті викликається
метод CommitTransactionдля того, щоб зміни було внесено в базу даних.
Наступним кроком є виклик методу, який було розроблено раніше, а саме,
методуafterCreate, далі повертаємо з об’єктуEntityEntry значення поля Entity.
Крім цього весь код знаходиться всередині конструкції try, catch для того,
щоб у разі виникнення помилки, транзакцію не булазакешовано назавжди в
пам’яті комп’ютера. У випадку, якщо помилка виникла необхідно викликати
метод RollbackTransactionв класі контекст методу.
На рисунку 3.13 наведено код програми методу, що розглянуто вище.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 46
Рисунок 3.13 – Код програми для створення самого об’єктуTask<TEntity>
Наступним кроком необхідно реалізувати можливість оновлювати
дані.Для цього було створено методи BeforeUpdate та AfterUpdateпо аналогії
зі створенням методів BeforeCreate та AfterCreate.
Нижче на рисунку 3.14 наведено код програми для створення методів
BeforeUpdate та AfterUpdate.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 47
Рисунок 3.14 – Код програми для створення методів BeforeUpdate та
AfterUpdate
Після виконаних налаштування з’являється можливість створення
самого методу для оновлення. Даний метод має наступний формат: повертає
об’єкт типу Task<TEntity> та приймає в якості об’єктів ключ типу TKey, а
також сутність типу TEntity. В процесі роботи з методом перший крок є
аналогічним до кроку, що виконується при створені об’єкту, необхідно
перевірити те, чи переданий об’єкт не пустий. У випадку, якщо об’єкт є
пустим, то повернути пусте значення не відтворюючи ніяких операцій
відносно об’єкту. Наступним кроком буде отримання оригінального об’єкту
виконуючи пошук по його ключу за допомогою реалізованого раніше методу
GetById та передати в нього ключ. Якщо отримане значення не є пустим, то
необхідно провести пошук в кеші самого контексту. При цьомунеобхідно
викликати в класі контекст метод Set та передати в нього об’єкт
узагальненого типу TEntity.Наступним кроком є виклик методуFindAsync та
передати нульове значення, у випадку, якщо значення не знайденов кеші, то
повертаємо пустий об’єкт, не виконуючи ніяких додаткових кроків; якщо
об’єкт з кешу було отримано не пустим, то необхідно відносно отриманого
об’єкту замінити значення його поля State на Detached, для того, щоб об’єкт
не викликав помилок відносно кешованих даних. Далі, для початку
транзакції, необхідно викликати у контексті метод BeginTransaction,
після,необхідно, викликати метод BeforeUpdate та отримати з нього
модифікований об’єкт. Наступним кроком є виклик у контекст методуUpdate
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 48
та передати в нього оновлену сутність, а потім викликати з контексту метод
SaveChangesAsync для можливості збереження даних.Щоб контекст не
продовжував виконувати кешувати цих даних, необхідно змінити значення
State у оновлюваному об’єкті на значення Detached, далі викликати у
контексті викликати метод CommitTransaction та метод AfterUpdate. Після
виконаних викликів необхідно повернути з результатуEntityEntry поле Еntity.
За аналогією для написаного коду для методу створення об’єкту весь
реалізований код для оновлення об’єкту поміщено всередині конструкції
trycatch, для якого в разі помилки в контексті необхідно викликати метод
RollbackTransaction.
Код програми для оновлення об’єктунаведено на рисунку 3.15.
Наступним кроком необхідно реалізувати видалення сутності.Для
цього необхідно реалізувати два наступних метода, а саме,BeforeDelete та
AfterDelete для операцій, що виконуються передта після виконання операції
видалення.
Створюються два наступних методи:BeforeDelete та AfterDelete, де для
BeforeDeleteмає бути наступна сигнатура: методунеобхідно повертати об’єкт
типу TEntityта приймати об’єкт типу TEntity.В наявній реалізації даний
метод просто повертає сутність, не виконуючижодних дій з ним. В методі
AfterDelete наступна сигнатура: даний об’єкт нічого не повертає, але приймає
в собі об’єкт типу TEntity.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 49
Рисунок 3.15 – Код програми для оновлення об’єкту
Код програми для видалення об’єктунаведено на рисунку 3.16.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 50
Рисунок 3.16 – Код програми для видалення об’єкту
Наступним кроком необхідно створити самий метод для виконання
видалення.Для цього необхідно оголосити метод з наступною сигнатурою:
метод має повертати об’єкт Task та передавати ключ типу TKey, далі, перш
за все необхідно почати транзакцію використовуючи методу для виклику у
контекста методуBeginTransaction, далі необхідно створити сутність
виконуючи передачу в нього ключа;наступним кроком необхідно отримати
модифіковану сутність з методу BeforeDelete та викликати у контекста метод
Remove. Після виконаних викликівнеобхідно викликати у контекста
збереження бази даних та викликати метод AfterDelete.Якщо отриманий
результат буде успішним, необхідно викликати у контекста
методCommitTransaction, що завершає транзакцію. Весь код поміщено
всередині конструкції trycatch і в разі помилки в контексті необхідно
викликати метод RollbackTransaction.
Код програми для створення самого об’єктунаведено на рисунку 3.17.
Останнім методом, що необхідно реалізувати – швидка перевірка
наявності елемента з таким ключем в таблиці. Даний метод представлено в
наступному форматі: метод має повертати Task<bool> та приймати ключ
типу TKey.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 51
Рисунок 3.17– Код програми для створення самого об’єкту
Для того, щоб виконати перевірку наявності елементу з таким ключем
необхідно отримати список наших об’єктів з методу GetQueryable, та
наступним кроком, викликати метод з цього списку AnyAsync, при цьому,
передаючи за допомогою лямбди в нього предикат, який порівнює ключ з
об’єктом х.
Код програми для розглянутого методу наведено на рисунку 3.18.
Рисунок 3.18– Код програми для швидкої перевірки наявності елементу
Після того, як базовий сервіс було створено, необхідно розробити
сервіс, що являється нащадком цього сервісу. При цьому необхідно створити
інтерфейс, в якому в генерації містяться наступні класи – переданий клас
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 52
Example в якості TEntity, тип long в якості ключа і ExampleFilter в якості
фільтру за яким буде виконуватися сортування, фільтрація та ін., та
наслідуватися від нашого базового інтерфейсу. Реалізація інтерфейсу для
даного сервісу завершується такими налаштуваннями.
На рисунку 3.19 наведено код створення нащадку для базового сервісу.
Рисунок 3.19 – Код створення нащадку для базового сервісу
Наступним кроком необхідно реалізувати сам сервіс, що має
назвуExampleServiceтанеобхідно його унаслідувати від базового сервісу та
передати для генерації ті ж самі типи, що буловказано при розробці
інтерфейсу.Дані потрібно реалізуватися від інтерфейсу IExampleService, як
результат взаємодія з сервісом завершена таінтерфейс повністю готовий до
роботи. Якщо необхідно змінити якийсь метод або ж доповнити його, дану
операцію можна зробити за допомогою override. Давайте розглянемо це на
прикладі включення в додатковий елемент внутрішнього типу. При
цьомунеобхідно перевизначити метод GetQueryable за допомогою overrideі
викликати в нього базовий метод.Далі викликати метод Includeі передати в
нього лямбда функцію із назвою поля, що необхідно включити у вибірку.
Код для розглянутого методу наведено на рисунку 3.20.
Після того, як сервіс було реалізовано його необхіднопроініціалізувати
в DI контейнер.Щоб виконати ініціалізацію в класі Startup в методі
ConfigureServicesнеобхідно викликати метод з об’єкта services типу
IServiceCollection наступним чиномservices.AddTransient<IExampleService,
ExampleService>().
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 53
Рисунок 3.20 – Код реалізації сервісу ExampleService
Тепер у випадку, коли необхідно буде застосувати даний сервіс в інших
сервісах або контролері, то необхідно отримати його інтерфейс у
конструкторі, а вже потім оновити об’єкт одержаними даними.
На прикладі застосування реалізованого сервісу матиме наступний
виглядає, як на рисунку 3.21.
Рисунок 3.21 - Код для застосування сервісу ExampleService
Наступним кроком, який необхідно зробити в процесі дослідження, це
виконати методів та визначити різницю в роботі між базовими та
модифікованими методами. Для цього виконаємо 10 тестових запусків для
тестування наступних методів: оновлення, створення, отримання та
видалення.
Результати, що було отримано в процесі тестування наведено на
рисунках 3.22 – 3.24.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 54
Рисунок 3.22 –Результати виконання методу створення
Рисунок 3.23– Результати виконання методу оновлення
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 55
Рисунок 3.24– Результат виконання процесу отримання даних з бази
даних
Рисунок 3.25–Результат виконання методу видалення даних з бази
даних
В процесі проведення експеременту було визначено, що різниця між
елементами відповідно до швидкодії мінімальна, в середньому вона складає
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 56
біля 0,04 мс. Але якщо порівнювати дані методи в площі швидкості розробки,
то в такому випадку, модифікований варіант буде набагато вигіднішим для
нових проектів, що містять більше 3-4 сутностей у яких логіка роботи не
занадто відрізняється, що надає вищу ефективність в часі розробки в
порівнянні з тим, щоб просто писати ту саму частину коду декілька разів.
В таблиці 3.1 наведено результати швидкості циклу обслуговування
записів CRUD, які зберігаються в системах управління базами даних сервісу
відносно сутності в годинах.
Таблиця 3.1 – Результати швидкості CRUD сервісу відносно
сутності в годинах
1 2 3 4 5 6 7 8
Стандартні 4 8 12 16 20 24 28 32
методи
Модифіковані 7 9 11 13 15 17 19 21
методи
Відповідно до отриманих в
таблицірезультатівможнавизначити,модернізованіметодизначнопокращують
швидкістьрозробки, процесїхпідтримки, а такожрозумінняреалізованогокоду.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 57
ВИСНОВКИ
В процесі виконання кваліфікаційної роботи бакалавра було
досліджено актуальну тему модернізації існуючих методів та паттернів на
основі платформи .NET.Було проведено аналіз існуючих на сьогодні
модифікацій для роботи з існуючою обгорткою .NET, що побудована на
типізованій мові програмування C#, що в свою чергу, має ряд переваг серед
популярних існуючих мов.
Під час дослідження було проведено теоретичний та практичний аналіз
готових рішень, визначено основні переваги оновлених інструментів, що
використовуються в роботі з .NET орієнтованими додатками під час
взаємодії з базами даних. У результаті було реалізовано модифіковані
методи, які стануть ключовими під час вирішення проблеми ціни проекту, а
саме: метод для сортування елементу за будь-яким полем в базі даних,
універсальний репозиторій і методи, що застосовуються для часткового
оновлення сутності.
В першому розділі кваліфікаційної роботи було розглянуто
платформу .NET, її основні напрямки застосування, а також бібліотеки,
інструменти, фреймворки, що використовуються в процесі вирішення
проблем на тій або іншій платформі, або напрямку. Також, розглянуто
виконуюче середовище CLR та принципи платформи. Крім цього, було
проведено дослідження та проаналізовано існуючі аналоги, визначено
переваги та недоліки кожного з них, як в площі швидкодії програм, так і в
площі швидкості розробки. Для вирішення проблем, що впливає на ціну
проекту,було обрано мову програмування C# і наведено приклади, як можна
цього досягти .
В другому розділі було надано опис, що таке ORM, проведено
дослідження трьох з них відповідно до мови C#, а саме: ADO .NET, Entity
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 58
Framework Core, Dapper,. Також, щоб проаналізувати обрані бази даних було
реалізовано три базові вибірки елементу зі списку елементів по
ідентифікатору, одного елементу по ідентифікатору, для списку елементів по
ідентифікатору із вкладенням. Проаналізувавши бібліотеки було визначено їх
переваги та недоліки відповідно до швидкості та зручності, а також було
обрано одну для модифікації, а саме, Entity Framework Core.
Також в другому розділі було наведено опис та проведено огляд всіх
базових методів взаємодії з базою даних: оновлення, створення,редагування
та видалення об’єкту. Зроблено висновки та описано переваги та недоліки
дій, які рекомендує компанія Microsoft.
В третьому розділі реалізовано самі методи тапроведено їх
дослідження В результаті було розроблено метод для сортування елементу за
будь-яким полем в базі даних, методи для універсального репозиторію та для
часткового оновлення сутності. Було досліджено та проаналізовано переваги
і недоліки модифікованих методів,представлено код їх реалізації.
Для реалізованих модифікованих методів було виконано порівняння із
стандартними методами за наступними показниками: швидкодія та
швидкість розробки. Також на основі отриманих в процесі дослідження
даних було побудовано графіки порівнянь.
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 59
ПЕРЕЛІК СКОРОЧЕНЬ ТА УМОВНИХ ПОЗНАЧЕНЬ
API Application Programming Interface
REST Representational State Transfer
HTTP Hyper Text Transfer Protocol
XML Extensible Markup Language
SSL Secure Sockets Layer
БСЗ Бланки суворої звітності
СУБД Система управління базами даних
IDE Integrated Development Environment
KVM Kernel-based Virtual Machine
TPC Transaction Processing Performance Council
DV Domain Validation
OV Organization Validation
EV Extended Validation
ORM Object-Relational Mapping
CLR Common Language Runtime
CLI Common Language Infrastructure
UX User Experience
UI User Interface
DDL Data Definition Language
DML Data Manipulation Language
ADO ActiveX Data Objects
EF Entity Framework
SOAP Simple Object Access Protocol
WCF Windows Communication Foundation
WPF Windows Presentation Foundation
ЧДТУ.2319034.005ПЗ
Зм. Лист № докум. Підпис Дата 60
ДОДАТОК А
«ЗАТВЕРДЖУЮ»
Завідувач кафедри ІБ та КІ
д.т.н., професор Володимир РУДНИЦЬКИЙ
__________________
«___» _____________ 2023 р.
Спосіб модифікації методів платформи .Net для
поліпшення читабельності коду
Специфікація
482.ЧДТУ.39034-01
Листів 2
Розробник _______________ Байрамгелді АННАГЕЛДІЄВ
Керівник _______________ Тетяна МИРОНЮК
Черкаси 2023
2
482.ЧДТУ.39034-01
Позначення Найменування Примітка
Документація
482.ЧДТУ.39034-01 12 01 Текст програми
ДОДАТОК Б
Спосіб модифікації методів платформи .Net для
поліпшення читабельності коду
Текст програми
482.ЧДТУ.39034-01 12 01
Листів 14
Розробник: Байрамгелді АННАГЕЛДІЄВ
Черкаси 2023
2
482.ЧДТУ.39034-01 12 01
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
public class CrudServiceBase<TEntity, TKey, TContext> :
ICrudServiceBase<TEntity, TKey>, IDisposable
where TKey : IEquatable<TKey>
where TEntity : class, IDbEntityBase<TKey>
where TContext : DbContext, ITransactionalDbContext
{
public bool ReobtainAfterWrite { get; set; }
protected bool ResetIdBeforeCreate { get; set; }
protected TContext Context { get; private set; }
public CrudServiceBase(TContext context)
{
Context = context;
ReobtainAfterWrite = false;
ResetIdBeforeCreate = true;
}
protected virtual IQueryable<TEntity> GetQueryable()
{
IQueryable<TEntity> query =
Context.Set<TEntity>();//.ShowDeleted(ReacquireAfterWrite);
/*if (!ShowDeleted)
{
query = query.Where(x => x.DeletionMark == false);
}*/
return query.AsNoTracking();
}
public virtual async Task<IEnumerable<TEntity>> Get()
{
return await GetQueryable().ToListAsync();
3
482.ЧДТУ.39034-01 12 01
}
public virtual async Task<PagedResponse<TEntity>> Get(PageInfo
pageInfo)
{
var result = await GetQueryable()
.OrderBy(m => m.Id)
.Paginate(pageInfo);
return result;
}
public virtual async Task<TEntity> GetById(TKey id)
{
var result = await GetQueryable()
.SingleOrDefaultAsync(x => x.Id.Equals(id));
return result;
}
protected virtual TEntity BeforeCreate(TEntity entity)
{
return entity;
}
protected virtual void AfterCreate(TEntity entity)
{
return;
}
public /* */ virtual async Task<TEntity> Create(TEntity entity) // !!!
{
if (entity == null)
{
return null;
}
if (ResetIdBeforeCreate)
{
//entity.Id = 0;
Type type = entity.GetType();
type.InvokeMember(
nameof(entity.Id),
4
482.ЧДТУ.39034-01 12 01
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.SetProperty |
System.Reflection.BindingFlags.Instance,
null, entity, new object[] { 000000000 }
);
}
try
{
Context.BeginTransaction();
entity = BeforeCreate(entity);
///var date = DateTime.UtcNow;
///entity.DateCreated = date;
///entity.DateModified = date;
var result = Context/*.Set<TEntity>()*/.Add(entity);
var rowsAffected = await Context.SaveChangesAsync();
result.State = EntityState.Detached;
if (ReobtainAfterWrite)
{
entity = (await GetQueryable()
.SingleOrDefaultAsync(x => x.Id.Equals(result.Entity.Id)));
}
else
{
entity = result.Entity;
}
Context.CommitTransaction();
AfterCreate(entity);
return entity;
}
catch (Exception e)
{
Context.RollbackTransaction();
throw e;
5
482.ЧДТУ.39034-01 12 01
}
}
public /* */ virtual async Task Create(ICollection<TEntity> entities) // !!!
{
if (entities == null)
{
return;
}
if (ResetIdBeforeCreate)
{
foreach (var entity in entities)
{
//entity.Id = 0;
Type type = entity.GetType();
type.InvokeMember(
nameof(entity.Id),
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.SetProperty |
System.Reflection.BindingFlags.Instance,
null, entity, new object[] { 000000000 }
);
}
}
try
{
Context.BeginTransaction();
///entity = BeforeCreate(entity);
///var date = DateTime.UtcNow;
///entity.DateCreated = date;
///entity.DateModified = date;
Context/*.Set<TEntity>()*/.AddRange(entities);
var rowsAffected = await Context.SaveChangesAsync();
Context.CommitTransaction();
///AfterCreate(entity);
6
482.ЧДТУ.39034-01 12 01
return;
}
catch (Exception e)
{
Context.RollbackTransaction();
throw e;
}
}
protected virtual TEntity BeforeUpdate(TEntity entity, TEntity origin)
{
return entity;
}
protected virtual void AfterUpdate(TEntity entity, TEntity origin)
{
return;
}
public /* virtual */ async Task<TEntity> Update(TKey id, TEntity entity)
// !!!
{
if (entity == null)
{
return null;
}
TEntity origin = await GetQueryable()
.SingleOrDefaultAsync(x => x.Id.Equals(id));
if (origin == null)
{
// Оригинал отсутствует в базе, но может в кэше - достаём:
origin = await Context.Set<TEntity>().FindAsync(id);
if (origin == null)
{
return null;
}
Context.Entry(origin).State = EntityState.Detached;
}
7
482.ЧДТУ.39034-01 12 01
//entity.Id = id;
Type type = entity.GetType();
type.InvokeMember(
nameof(entity.Id),
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.SetProperty |
System.Reflection.BindingFlags.Instance,
null, entity, new object[] { id }
);
try
{
Context.BeginTransaction();
entity = BeforeUpdate(entity, origin);
///entity.DeletionMark = origin.DeletionMark;
///entity.DateCreated = origin.DateCreated;
///entity.DateModified = DateTime.UtcNow;
// Context.Entry(origin).CurrentValues.SetValues(entity);
//Context.Entry(entity).State = EntityState.Modified;
var result = Context.Update(entity);
var rowsAffected = await Context.SaveChangesAsync();
result.State = EntityState.Detached;
if (ReobtainAfterWrite)
{
entity = await GetQueryable()
.SingleOrDefaultAsync(x => x.Id.Equals(result.Entity.Id));
}
else
{
entity = result.Entity;
}
Context.CommitTransaction();
AfterUpdate(entity, origin);
8
482.ЧДТУ.39034-01 12 01
return entity;
}
catch (Exception e)
{
Context.RollbackTransaction();
throw e;
}
}
protected virtual TEntity BeforeDelete(TEntity entity)
{
return entity;
}
protected virtual void AfterDelete(TEntity entity)
{
return;
}
public /* virtual */ async Task Delete(TKey id) // !!!
{
// var entity = await GetQueryable()
// .SingleOrDefaultAsync(x => x.Id == id);
TEntity entity = await Context.Set<TEntity>().FindAsync(id);
Context.Entry(entity).State = EntityState.Detached;
if (entity == null)
{
return;
}
try
{
Context.BeginTransaction();
entity = BeforeDelete(entity);
Context.Remove(entity);
await Context.SaveChangesAsync();
AfterDelete(entity);
Context.CommitTransaction();
9
482.ЧДТУ.39034-01 12 01
}
catch (Exception e)
{
Context.RollbackTransaction();
throw e;
}
}
public virtual async Task<bool> IsExists(TKey id)
{
return await GetQueryable().AnyAsync(x => x.Id.Equals(id));
}
#region IDisposable
private bool disposed = false;
public void Dispose()
{
if (!disposed && Dispose(true))
{
disposed = true;
GC.SuppressFinalize(this);
}
}
protected virtual bool Dispose(bool manual)
{
if (manual)
{
//Context?.Dispose(); // Don't need due dependency injection
Context = null;
}
return true;
}
~CrudServiceBase()
{
disposed = !disposed ? Dispose(false) : true;
}
#endregion
}
}
10
482.ЧДТУ.39034-01 12 01
public abstract class CrudServiceBaseWithFiltration<TEntity, TKey, TFilter,
TContext> : CrudServiceBase<TEntity, TKey, TContext>,
ICrudServiceBaseWithFiltration<TEntity, TKey, TFilter>
where TKey : IEquatable<TKey>
where TEntity : class, IDbEntityBase<TKey>
where TContext : DbContext, ITransactionalDbContext
where TFilter : Filter<TEntity>, new()
{
protected IList<string> AllowedOrderProperties;
protected bool? OrderByDescending;
protected CrudServiceBaseWithFiltration(TContext context) : base(context)
{
}
protected TFilter GetSortingFilterOrDefault(TFilter filter)
{
filter = filter ?? new TFilter();
if (AllowedOrderProperties == null ||
AllowedOrderProperties.IndexOf(filter.OrderBy) < 0)
{
// Если поле не задано или неизвестное, сортировка по умолчанию
filter.OrderBy = AllowedOrderProperties?[0];
filter.OrderByDescending = OrderByDescending;
}
// Если порядок не указан - по умолчанию
filter.OrderByDescending = filter.OrderByDescending ??
OrderByDescending;
return filter;
}
protected IQueryable<TEntity> GetFilteredQueryable(TFilter filter)
{
filter = GetSortingFilterOrDefault(filter);
var query = Filter(filter);
if (!String.IsNullOrEmpty(filter.OrderBy))
{
query = query.OrderBy(filter.OrderBy, filter.OrderByDescending ??
false);
}
else
{
11
482.ЧДТУ.39034-01 12 01
query = query.OrderByDescending(x => x.Id);
}
return query;
}
public virtual async Task<IEnumerable<TEntity>> Get(TFilter filter)
{
return await GetFilteredQueryable(filter).ToListAsync();
}
public virtual async Task<PagedResponse<TEntity>> Get(PageInfo pageInfo,
TFilter filter)
{
return await GetFilteredQueryable(filter).Paginate(pageInfo);
}
protected virtual IQueryable<TEntity> Filter(TFilter filter)
{
return GetQueryable();
}
}
public class ExampleService : ServiceBaseWithFiltration< Example,
ExamplexFilter>, IBundleService
{
public ExampleService(MainDbContext context) : base(context)
{
}
protected override IQueryable< Example > GetQueryable()
{
return base.GetQueryable()
.Include(x => x.StoredFile)
;
}
protected override IQueryable< Example > Filter(ExampleFilter filter)
{
return base.Filter(filter)
.Where(x => String.IsNullOrEmpty(filter.Name) ||
x.Name.Contains(filter.Name))
.Where(x => String.IsNullOrEmpty(filter.Title) ||
x.Title.Contains(filter.Title))
.Where(x => !filter.Type.HasValue || x.Type.Equals(filter.Type.Value))
12
482.ЧДТУ.39034-01 12 01
;
}
public async Task<Example> GetByNameAsync(string name)
{
return await this.Context.Examples.FirstOrDefaultAsync(b =>
b.Name.Equals(name));
}
} public static void UpdatEntity<T>(this ApplicationDbContext source, T
target) where T : class
{
source.Attach(target);
var propertiesOfType = target.GetType().GetProperties();
foreach (var prop in propertiesOfType)
{
if (prop.Name != "Id")
{
var value = prop.GetValue(target);
if (value != null)
{
source.Entry(target).Property(prop.Name).IsModified = true;
}
}
}
source.SaveChanges();
}
public static class UpdateEntityExtension
{
public static T UpdatEntity<T>(this T source, T target ) where T: class
{
var propertiesOfType = target.GetType().GetProperties();
foreach (var prop in propertiesOfType)
{
if (prop.Name != "Id")
{
var value = prop.GetValue(target);
if (value != null)
{
13
482.ЧДТУ.39034-01 12 01
var typeValue = value.GetType();
var defaultValue = typeValue.IsValueType ?
Activator.CreateInstance(typeValue) : null;
if (!value.Equals(defaultValue))
{ source.GetType().GetProperty(prop.Name).SetValue(source,value);
}
}
}
}
return source;
}
}
public static class QueryableExtensions
{
public static IQueryable OrderBy(this IQueryable query, String OrderProperty,
Boolean IsDescending)
{
var typeOfElement = typeof(TEntity);
var propertyType = typeOfElement .GetProperty(orderProperty);
var parameterExpression = Expression.Parameter(typeOfElement , "p");
var memberAccess =
Expression.MakeMemberAccess(parameterparameterExpression, propertyType);
var orderByExpression = Expression.Lambda(memberAccess,
parameterExpression);
string orderBy ="OrderByDescending";
var typeOfQueryable = typeof(Queryable);
var types = new Type[] { typeOfElement , property.PropertyType };
var expressionQuoteResult = Expression.Quote(orderByExpression );
if(!IsDescending){
orderBy= "OrderBy";
}
return query.Provider.CreateQuery(Expression.Call(
typeOfQueryable ,
orderBy ,
types,
query.Expression,
expressionQuoteResult
14
482.ЧДТУ.39034-01 12 01
);
}
);
}
СПИСОК ВИКОРИСТАНИХ ДЖЕРЕЛ
1. Адам Фріман. Pro Entity Framework Core 2 for ASP.NET Core MVC.
Apress 2018, 630 с. ISBN: 978-1-4842-3435-8.
2. Dapper tutorial [Електронний ресурс]: Режим доступу: https://dapper-
tutorial.net/.
3. Astonishing Performance of .NET 5 [Електронний ресурс]: Режим
доступу: https://alexyakunin.medium.com/astonishing-performance-of-net-
5-7803d69dae2e.
4. The Computer Language Benchmark Game [Електронний ресурс]: Режим
доступу: https://benchmarksgame-
team.pages.debian.net/benchmarksgame/fastest/csharp.html.
5. Bennett Jim. Xamarin in Action: Manning Publications, 2018. – 608 с.
6. Brown P. Windows Store App Development: C# and XAML:Manning,
2013. – 592 p. Режим доступу:
http://www.sun.com/koi/news/sunburst/95.html
7. gRPC Performance in Net 5[Електронний ресурс]: Режим доступу:
https://devblogs.microsoft.com/aspnet/grpc-performance-improvements-in-
net-5/
8. Aponte Michele. Building Single Page Applications in .NET Core 3:
Jumpstart Coding Using Blazor and C# Apress, 2020. – 117 с. – ISBN
1484257464.
9. Himschoot Peter. Blazor Revealed: Building Web Applications in .NET
Apress, 2019. – 247 с. – ISBN 978-1484243428.
10.Як завдяки WebAssembly вдалося прискорити додаток в 20 разів
[Електронний ресурс]: Режим доступу:
https://tproger.com/translations/wasm-site-speed-up/.
Лист
ЧДТУ.2319034.005 ПЗ т
Зм. Лист № докум. Підпис Дат 76
а
11.Chowdhury Kunal. Mastering Visual Studio 2017 Packt Publishing, 2017. –
466 с. – ISBN 978-1-78728-190-5.
12. Gąsior Łukasz. ReSharper Essentials Packt, 2014. – 124 с. – ISBN: 978-1-
84969-870-2.
13.Write unit tests for managed code[Електронний ресурс]: Режим доступу:
https://docs.microsoft.com/en-us/visualstudio/test/walkthrough-creating-
and-running-unit-tests-for-managed-code?view=vs-2019.
14.Entity Framework Core [Електронний ресурс]: Режим доступу:
https://docs.microsoft.com/en-us/ef/core/.
15. Learn Entity Framework Core [Електронний ресурс]: Режим доступу:
https://www.learnentityframeworkcore.com/.
Лист
ЧДТУ.2319034.005 ПЗ т
Зм. Лист № докум. Підпис Дат 77
а