Teknologi WarisanPeringatan: ASP.NET MVC sudah usang. Dianjurkan untuk menggunakan ASP.NET Core. Tetapi jika Anda tertarik, maka bacalah.
 Saya memutuskan untuk sedikit memperluas 
artikel sebelumnya tentang ASP.NET MVC dan MySQL . Itu tentang bekerja dengan MySQL di ASP.NET MVC bukan melalui ORM Entity Framework (EF) yang hampir standar, tetapi menggunakan akses langsung ke DBMS melalui ADO.NET. Dan implementasi metode akses ini diberikan. Dan meskipun metode ini sudah usang dan tidak direkomendasikan untuk digunakan, kadang-kadang berguna: misalnya, dalam aplikasi yang sangat dimuat atau ketika pengembang dihadapkan pada situasi di mana ORM tidak dapat menghasilkan kueri SQL yang berfungsi dengan benar. Dan kadang-kadang Anda dapat menggabungkan kedua metode dalam aplikasi - baik melalui ORM dan melalui ADO.NET. Akibatnya, saya berpikir dan memutuskan untuk menyelesaikan aplikasi: menambahkan implementasi repositori untuk Kerangka Entitas ke dalamnya dan membuat pilihan mereka bergantung pada parameter aplikasi menggunakan Penyelesai Ketergantungan.
Semua kode dapat diambil di sini di 
alamat ini , di bawah kode ini akan disajikan sebagian dengan tautan kecil dan penjelasan sehubungan dengan 
proyek sebelumnya . Dan di sini Anda dapat 
melihat aplikasinya .
Kami mengubah proyek
1. Untuk menggunakan Entity Framework dengan MySQL, kita perlu menginstal pustaka 
MySQL.Data.EntityFramework (Anda tentu saja dapat memiliki yang lain, hanya saja ini dari Oracle, pemilik MySQL).

Ini akan menarik 
MySQL.Data dan 
EntityFramework itu sendiri . Perubahan berikut dibuat pada 
file web.config :
<entityFramework> <providers> <provider invariantName="MySql.Data.MySqlClient" type="MySql.Data.MySqlClient.MySqlProviderServices, MySql.Data.EntityFramework, Version=8.0.19.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d" /> </providers> </entityFramework> 
Konflik yang menarik muncul dengan 
MySQL.Data - karena 
MySQL.Data.EntityFramework memerlukan versi 
MySQL.Data minimal 8.0.19, itu diperbarui ... dan proyek berhenti bekerja. Kesalahan mulai terjadi:

«Ubiety.Dns.Core» . . , , . ( HRESULT: 0x80131045)Rupanya, 
perakitan yang tidak ditandatangani Ubiety.Dns.Core ditambahkan ke 
MySQL.Data 8.0.19 . Saya juga harus memasukkan komponen ini melalui Nuget dalam proyek. Kesalahan hilang.
2. Selain itu, untuk mengimplementasikan implementasi dependensi, kami menambah proyek Ninject - wadah untuk mengimplementasikan dependensi (DI).
3. Kami akan sedikit mengubah struktur proyek: kami akan menempatkan file repositori ke dalam direktori 
Repositori terpisah dan membuat subdirektori 
ADO.NET di dalamnya (kami akan mentransfer file 
LanguagesRepository.cs dan 
UsersRepository.cs yang ada di sana ) dan 
EF (akan ada file repositori untuk Entity Framework di sini).
4. Selain itu, parameter aplikasi telah ditambahkan ke 
file web.config di bagian 
appConfig : 
<add key="ConnectionMethod" value="ADO.NET" /> . Aplikasi akan mengambil dua nilai: "Entity Framework" atau "ADO.NET". 
Menambahkan tautan ke parameter ini ke file 
Base.cs :
 public static string ConnectionMethod { get { return System.Configuration.ConfigurationManager.AppSettings["ConnectionMethod"]; } } 
Entity Framework dan MySQL - repository
Tambahkan file 
DbContext.cs dengan kelas 
EFDbContext ke 
EFDbContext Repository \ EF :
 public class EFDbContext : DbContext { public EFDbContext() : base(Base.ConnectionString) { } public DbSet<UserClass> Users { get; set; } public DbSet<LanguageClass> Languages { get; set; } } 
Di dalamnya, kami menentukan string koneksi DBMS yang digunakan dan set data 
Users dan 
Languages .
Tambahkan file 
LanguagesRepository.cs dengan kelas 
LanguagesRepositoryEF :
 public class LanguagesRepositoryEF : ILanguagesRepository { private EFDbContext context = new EFDbContext(); public IList<LanguageClass> List() { return context.Languages.OrderBy(x => x.LanguageName).ToList(); } } 
Dan file 
UsersRepository.cs dengan kelas 
UsersRepositoryEF :
 public class UsersRepositoryEF : IUsersRepository { private EFDbContext context = new EFDbContext(); public IList<UserClass> List() { return context.Users.ToList(); } public IList<UserClass> List(string sortName, SortDirection sortDir, int page, int pageSize, out int count) { count = context.Users.Count(); if (sortName != null) return context.Users.OrderByDynamic(sortName, sortDir).Skip((page - 1) * pageSize).Take(pageSize).ToList(); else return context.Users.OrderBy(o => o.UserID).Skip((page - 1) * pageSize).Take(pageSize).ToList(); } public bool AddUser(UserClass user) { user.Language = context.Languages.Find(user.Language.LanguageID); if (user.Language != null && context.Users.Add(user) != null) { try { context.SaveChanges(); } catch (System.Exception ex) {} } return user.UserID > 0; } public UserClass FetchByID(int userID) { UserClass user = null; try { user = context.Users.Find(userID); } catch (System.Exception ex) { } return user; } public bool ChangeUser(UserClass user) { bool result = false; user.Language = context.Languages.Find(user.Language.LanguageID); if (user.Language != null) { UserClass olduser = context.Users.Find(user.UserID); if (olduser != null) { olduser.Email = user.Email; olduser.Loginname = user.Loginname; olduser.Language = user.Language; olduser.SupporterTier = user.SupporterTier; try { result = context.SaveChanges() > 0; } catch (System.Exception ex) { } } } return result; } public bool RemoveUser(UserClass user) { bool result = false; UserClass olduser = context.Users.Find(user.UserID); if (olduser != null) context.Users.Remove(olduser); try { result = context.SaveChanges() > 0; } catch (System.Exception ex) { } return result; } } 
Dapat dilihat bahwa ukuran file jelas lebih pendek dari itu untuk ADO.NET - ORM melakukan pekerjaan kotor untuk kami - ia menciptakan query SQL sendiri.
Namun, saya menemukan beberapa poin yang masuk ke dalam implementasi ADO.NET, tetapi tidak berhasil di EF.
Hal pertama yang saya harus lakukan untuk mengubah file 
UserClass.cs (dalam direktori 
Domain ): tambahkan bidang lain untuk operasi normal koneksi antara tabel 
Users dan 
Languages :
 [HiddenInput(DisplayValue = false)] public int? LanguageID { get; set; } 
Dan yang kedua - ternyata bidang di MySQL seperti 
Enum tidak bekerja melalui EF. Kemungkinan besar, alasan untuk ini adalah bahwa enumerasi dalam kode adalah nilai integer, tetapi dari database nilai-nilai melalui EF dibaca sebagai teks (jika dalam query dari MySQL untuk membaca nilai-nilai bidang tipe enum MySQL mengembalikan hanya nilai teks dari enumerasi ini). Dan jika dalam versi untuk ADO.NET saya dapat menyiasati hal ini menggunakan 
CAST(u.SupporterTier AS UNSIGNED) as SupporterTier konstruksi 
CAST(u.SupporterTier AS UNSIGNED) as SupporterTier , kemudian dengan EF metamorfosis seperti itu ternyata tidak dapat diatasi bagi saya - tidak ada opsi yang dicoba muncul. Nah, karena teknologi 
Code First menghasilkan bidang tipe 
Enum sebagai bidang tipe INT, kami harus mengubah jenis bidang 
SupporterTier dalam database:
 CHANGE COLUMN `SupporterTier` `SupporterTier` INT(4) UNSIGNED NOT NULL DEFAULT '1' ; 
Pilih repositori menggunakan parameter aplikasi
Kami akan menggunakan implementasi melalui konstruktor, seperti yang tertulis di buku teks. Pertama, kita perlu membuat antarmuka untuk repositori bersama kita: membuat file 
LanguagesRepository.cs di direktori 
Repositori dengan konten:
 public interface ILanguagesRepository { IList<LanguageClass> List(); } 
Dan file 
UsersRepository.cs dengan konten:
 public interface IUsersRepository { IList<UserClass> List(); IList<UserClass> List(string sortName, SortDirection sortDir, int page, int pageSize, out int count); bool AddUser(UserClass user); UserClass FetchByID(int userID); bool ChangeUser(UserClass user); bool RemoveUser(UserClass user); } 
Kami mewarisi kelas yang sesuai dari antarmuka ini:
 public class LanguagesRepositoryADO : ILanguagesRepository public class UsersRepositoryADO : IUsersRepository public class LanguagesRepositoryEF : ILanguagesRepository public class UsersRepositoryEF : IUsersRepository 
Nah, pada pengontrol 
UsersController, kami membuat tambahan yang memungkinkannya bekerja dengan antarmuka ini:
 private ILanguagesRepository repLanguages; private IUsersRepository repUsers; public UsersController(ILanguagesRepository langsParam, IUsersRepository usersParam) { repLanguages = langsParam; repUsers = usersParam; } 
Dan di controller, kami mengubah tempat-tempat mengakses objek kelas-kelas ini ke objek 
repLanguages dan 
repUsers , masing-masing. Tetapi kita perlu melewatkan instance dari kelas repositori melalui konstruktor controller, yang, tentu saja, tidak nyaman. Untuk menghindarinya, kita membutuhkan ilmu sihir yang kuat seperti 
Dependency Resolver (DR). Dan untuk ini kita akan menggunakan Ninject:
Kami mendaftarkan DR di file 
Global.asax.cs dalam metode 
Application_Start :
 DependencyResolver.SetResolver(new NinjectDependencyResolver()); 
Buat file 
NinjectDependencyResolver.cs di direktori 
Infrastruktur dengan kelas 
NinjectDependencyResolver (diwarisi dari antarmuka 
IDependencyResolver ):
 public class NinjectDependencyResolver : IDependencyResolver { private IKernel kernel; public NinjectDependencyResolver() { kernel = new StandardKernel(); AddBindings(); } public object GetService(Type serviceType) { return kernel.TryGet(serviceType); } public IEnumerable<object> GetServices(Type serviceType) { return kernel.GetAll(serviceType); } private void AddBindings() { if (Domain.Base.ConnectionMethod == "Entity Framework") { kernel.Bind<ILanguagesRepository>().To<LanguagesRepositoryEF>(); kernel.Bind<IUsersRepository>().To<UsersRepositoryEF>(); } else { kernel.Bind<ILanguagesRepository>().To<LanguagesRepositoryADO>(); kernel.Bind<IUsersRepository>().To<UsersRepositoryADO>(); } } } 
Dan ternyata satu-satunya tempat di mana ditentukan metode mana yang bekerja dengan DBMS digunakan (langsung, melalui ADO.NET atau melalui Entity Framework) adalah metode 
AddBindings di kelas 
NinjectDependencyResolver . Sihir sungguhan jika Anda tidak tahu cara kerjanya.
Dalam metode 
AddBindings , tergantung pada nilai parameter aplikasi ConnectionMethod, 
IUsersRepository dan 
IUsersRepository dengan kelas tertentu yang menerapkan metode antarmuka. Karena ketika kami 
NinjectDependencyResolver aplikasi, kami mendaftarkan DR sebagai objek dari kelas 
NinjectDependencyResolver , dan di dalam kelas kami menentukan pengikatan antarmuka repositori ke kelas tertentu, ketika meminta kerangka kerja MVC untuk membuat 
UsersController pengontrol 
UsersController , Ninject ketika menganalisis kelas akan menemukan bahwa itu memerlukan implementasi 
IUsersRepository dan 
ILanguagesRepository dan 
IUsersRepository akan membuat instance kelas tertentu dan meneruskannya ke konstruktor kontroler (melalui DR dan kerangka kerja MVC).
Total
Aplikasi sekarang juga mendukung metode akses ke DBMS melalui ORM Entity Framework. Pada saat yang sama, metode akses melalui ADO.NET belum hilang dan dipilih ketika aplikasi diluncurkan oleh parameter, di mana kami menggunakan metode injeksi ketergantungan melalui konstruktor pengontrol menggunakan perpustakaan Ninject.

PS Dan akhirnya: Anda bisa melihat bagaimana proyek ini bekerja di 
alamat ini . Dan di 
sini Anda dapat mengunduh seluruh proyek. Nah, untuk heap - tautan ke 
blog saya .