Model penyedia Entity Framework 6
Model penyedia Kerangka Kerja Entitas memungkinkan Kerangka Kerja Entitas digunakan dengan berbagai jenis server database. Misalnya, satu penyedia dapat dicolokkan untuk memungkinkan EF digunakan terhadap Microsoft SQL Server, sementara penyedia lain dapat dicolokkan untuk memungkinkan EF digunakan terhadap Microsoft SQL Server Compact Edition. Penyedia untuk EF6 yang kami ketahui dapat ditemukan di halaman penyedia Kerangka Kerja Entitas.
Perubahan tertentu diperlukan untuk cara EF berinteraksi dengan penyedia untuk memungkinkan EF dirilis di bawah lisensi sumber terbuka. Perubahan ini memerlukan pembangunan kembali penyedia EF terhadap rakitan EF6 bersama dengan mekanisme baru untuk pendaftaran penyedia.
Membangun kembali
Dengan EF6 kode inti yang sebelumnya merupakan bagian dari .NET Framework sekarang dikirim sebagai rakitan out-of-band (OOB). Detail tentang cara membangun aplikasi terhadap EF6 dapat ditemukan di halaman Memperbarui aplikasi untuk EF6 . Penyedia juga harus dibangun kembali menggunakan instruksi ini.
Gambaran umum jenis penyedia
Penyedia EF benar-benar kumpulan layanan khusus penyedia yang ditentukan oleh jenis CLR yang diperluas layanan ini dari (untuk kelas dasar) atau menerapkan (untuk antarmuka). Dua layanan ini sangat mendasar dan diperlukan agar EF berfungsi sama sekali. Lainnya bersifat opsional dan hanya perlu diimplementasikan jika fungsionalitas tertentu diperlukan dan/atau implementasi default layanan ini tidak berfungsi untuk server database tertentu yang ditargetkan.
Jenis penyedia dasar
DbProviderFactory
EF bergantung pada memiliki jenis yang berasal dari System.Data.Common.DbProviderFactory untuk melakukan semua akses database tingkat rendah. DbProviderFactory sebenarnya bukan bagian dari EF tetapi bukan kelas dalam .NET Framework yang melayani titik masuk untuk penyedia ADO.NET yang dapat digunakan oleh EF, O/RM lain atau secara langsung oleh aplikasi untuk mendapatkan instans koneksi, perintah, parameter, dan abstraksi ADO.NET lainnya dengan cara agnostik penyedia. Informasi selengkapnya tentang DbProviderFactory dapat ditemukan dalam dokumentasi MSDN untuk ADO.NET.
DbProviderServices
EF tergantung pada memiliki jenis yang berasal dari DbProviderServices untuk menyediakan fungsionalitas tambahan yang diperlukan oleh EF di atas fungsionalitas yang sudah disediakan oleh penyedia ADO.NET. Dalam versi EF yang lebih lama, kelas DbProviderServices adalah bagian dari .NET Framework dan ditemukan di namespace Layanan System.Data.Common. Dimulai dengan EF6 kelas ini sekarang menjadi bagian dari EntityFramework.dll dan berada di namespace Layanan System.Data.Entity.Core.Common.
Detail selengkapnya tentang fungsionalitas mendasar dari implementasi DbProviderServices dapat ditemukan di MSDN. Namun, perhatikan bahwa pada saat penulisan informasi ini tidak diperbarui untuk EF6 meskipun sebagian besar konsep masih valid. Implementasi SQL Server dan SQL Server Compact dari DbProviderServices juga diperiksa ke basis kode sumber terbuka dan dapat berfungsi sebagai referensi yang berguna untuk implementasi lain.
Dalam versi lama EF, implementasi DbProviderServices untuk digunakan diperoleh langsung dari penyedia ADO.NET. Ini dilakukan dengan mentransmisikan DbProviderFactory ke IServiceProvider dan memanggil metode GetService. Ini menggabungkan penyedia EF dengan erat ke DbProviderFactory. Pengkodean ini memblokir EF agar tidak dipindahkan dari .NET Framework dan oleh karena itu untuk EF6, kopling ketat ini telah dihapus dan implementasi DbProviderServices sekarang terdaftar langsung dalam file konfigurasi aplikasi atau dalam konfigurasi berbasis kode seperti yang dijelaskan secara lebih rinci bagian Mendaftarkan DbProviderServices di bawah ini.
Layanan tambahan
Selain layanan mendasar yang dijelaskan di atas ada juga banyak layanan lain yang digunakan oleh EF yang selalu atau terkadang khusus penyedia. Implementasi khusus penyedia default dari layanan ini dapat disediakan oleh implementasi DbProviderServices. Aplikasi juga dapat mengambil alih implementasi layanan ini, atau memberikan implementasi ketika jenis DbProviderServices tidak menyediakan default. Ini dijelaskan secara lebih rinci di bagian Menyelesaikan layanan tambahan di bawah ini.
Jenis layanan tambahan yang mungkin menarik bagi penyedia tercantum di bawah ini. Detail selengkapnya tentang masing-masing jenis layanan ini dapat ditemukan dalam dokumentasi API.
IDbExecutionStrategy
Ini adalah layanan opsional yang memungkinkan penyedia menerapkan percobaan ulang atau perilaku lain saat kueri dan perintah dijalankan terhadap database. Jika tidak ada implementasi yang disediakan, maka EF hanya akan menjalankan perintah dan menyebarluaskan pengecualian apa pun yang dilemparkan. Untuk SQL Server, layanan ini digunakan untuk memberikan kebijakan coba lagi yang sangat berguna saat berjalan terhadap server database berbasis cloud seperti SQL Azure.
IDbConnectionFactory
Ini adalah layanan opsional yang memungkinkan penyedia untuk membuat objek DbConnection berdasarkan konvensi ketika hanya diberikan nama database. Perhatikan bahwa meskipun layanan ini dapat diselesaikan oleh implementasi DbProviderServices yang telah ada sejak EF 4.1 dan juga dapat secara eksplisit diatur dalam file konfigurasi atau dalam kode. Penyedia hanya akan mendapatkan kesempatan untuk menyelesaikan layanan ini jika terdaftar sebagai penyedia default (lihat Penyedia default di bawah) dan jika pabrik koneksi default belum diatur di tempat lain.
DbSpatialServices
Ini adalah layanan opsional yang memungkinkan penyedia untuk menambahkan dukungan untuk jenis spasial geografi dan geometri. Implementasi layanan ini harus disediakan agar aplikasi dapat menggunakan EF dengan jenis spasial. DbSpatialServices diminta dengan dua cara. Pertama, layanan spasial khusus penyedia diminta menggunakan objek DbProviderInfo (yang berisi nama invarian dan token manifes) sebagai kunci. Kedua, DbSpatialServices dapat diminta tanpa kunci. Ini digunakan untuk menyelesaikan "penyedia spasial global" yang digunakan saat membuat jenis DbGeography atau DbGeometry yang berdiri sendiri.
MigrationSqlGenerator
Ini adalah layanan opsional yang memungkinkan Migrasi EF digunakan untuk pembuatan SQL yang digunakan dalam membuat dan memodifikasi skema database oleh Code First. Implementasi diperlukan untuk mendukung Migrasi. Jika implementasi disediakan, implementasi juga akan digunakan saat database dibuat menggunakan penginisialisasi database atau metode Database.Create.
Func<DbConnection, string, HistoryContextFactory>
Ini adalah layanan opsional yang memungkinkan penyedia untuk mengonfigurasi pemetaan HistoryContext ke tabel yang __MigrationHistory
digunakan oleh MIGRASI EF. HistoryContext adalah Code First DbContext dan dapat dikonfigurasi menggunakan API fasih normal untuk mengubah hal-hal seperti nama tabel dan spesifikasi pemetaan kolom. Implementasi default layanan ini yang dikembalikan oleh EF untuk semua penyedia dapat berfungsi untuk server database tertentu jika semua pemetaan tabel dan kolom default didukung oleh penyedia tersebut. Dalam kasus seperti itu penyedia tidak perlu menyediakan implementasi layanan ini.
IDbProviderFactoryResolver
Ini adalah layanan opsional untuk mendapatkan DbProviderFactory yang benar dari objek DbConnection tertentu. Implementasi default layanan ini yang dikembalikan oleh EF untuk semua penyedia dimaksudkan untuk bekerja untuk semua penyedia. Namun, saat berjalan di .NET 4, DbProviderFactory tidak dapat diakses secara publik dari satu jika DbConnections-nya. Oleh karena itu, EF menggunakan beberapa heuristik untuk mencari penyedia terdaftar untuk menemukan kecocokan. Ada kemungkinan bahwa untuk beberapa penyedia heuristik ini akan gagal dan dalam situasi seperti itu penyedia harus menyediakan implementasi baru.
Mendaftarkan DbProviderServices
Implementasi DbProviderServices yang akan digunakan dapat didaftarkan baik dalam file konfigurasi aplikasi (app.config atau web.config) atau menggunakan konfigurasi berbasis kode. Dalam kedua kasus, pendaftaran menggunakan "nama invarian" penyedia sebagai kunci. Ini memungkinkan beberapa penyedia untuk didaftarkan dan digunakan dalam satu aplikasi. Nama invarian yang digunakan untuk pendaftaran EF sama dengan nama invarian yang digunakan untuk pendaftaran penyedia ADO.NET dan string koneksi. Misalnya, untuk SQL Server, nama invariant "System.Data.SqlClient" digunakan.
Pendaftaran file konfigurasi
Jenis DbProviderServices yang akan digunakan terdaftar sebagai elemen penyedia di daftar penyedia bagian entityFramework dari file konfigurasi aplikasi. Contohnya:
<entityFramework>
<providers>
<provider invariantName="My.Invariant.Name" type="MyProvider.MyProviderServices, MyAssembly" />
</providers>
</entityFramework>
String jenis harus berupa nama jenis yang memenuhi syarat perakitan dari implementasi DbProviderServices untuk digunakan.
Pendaftaran berbasis kode
Dimulai dengan penyedia EF6 juga dapat didaftarkan menggunakan kode. Ini memungkinkan penyedia EF untuk digunakan tanpa perubahan apa pun pada file konfigurasi aplikasi. Untuk menggunakan konfigurasi berbasis kode, aplikasi harus membuat kelas DbConfiguration seperti yang dijelaskan dalam dokumentasi konfigurasi berbasis kode. Konstruktor kelas DbConfiguration kemudian harus memanggil SetProviderServices untuk mendaftarkan penyedia EF. Contohnya:
public class MyConfiguration : DbConfiguration
{
public MyConfiguration()
{
SetProviderServices("My.New.Provider", new MyProviderServices());
}
}
Mengatasi layanan tambahan
Seperti disebutkan di atas di bagian Gambaran umum jenis Penyedia, kelas DbProviderServices juga dapat digunakan untuk menyelesaikan layanan tambahan. Ini dimungkinkan karena DbProviderServices mengimplementasikan IDbDependencyResolver dan setiap jenis DbProviderServices terdaftar ditambahkan sebagai "resolver default". Mekanisme IDbDependencyResolver dijelaskan secara lebih rinci dalam Resolusi Dependensi. Namun, tidak perlu memahami semua konsep dalam spesifikasi ini untuk menyelesaikan layanan tambahan di penyedia.
Cara paling umum bagi penyedia untuk menyelesaikan layanan tambahan adalah dengan memanggil DbProviderServices.AddDependencyResolver untuk setiap layanan di konstruktor kelas DbProviderServices. Misalnya, SqlProviderServices (penyedia EF untuk SQL Server) memiliki kode yang mirip dengan inisialisasi:
private SqlProviderServices()
{
AddDependencyResolver(new SingletonDependencyResolver<IDbConnectionFactory>(
new SqlConnectionFactory()));
AddDependencyResolver(new ExecutionStrategyResolver<DefaultSqlExecutionStrategy>(
"System.data.SqlClient", null, () => new DefaultSqlExecutionStrategy()));
AddDependencyResolver(new SingletonDependencyResolver<Func<MigrationSqlGenerator>>(
() => new SqlServerMigrationSqlGenerator(), "System.data.SqlClient"));
AddDependencyResolver(new SingletonDependencyResolver<DbSpatialServices>(
SqlSpatialServices.Instance,
k =>
{
var asSpatialKey = k as DbProviderInfo;
return asSpatialKey == null
|| asSpatialKey.ProviderInvariantName == ProviderInvariantName;
}));
}
Konstruktor ini menggunakan kelas pembantu berikut:
- SingletonDependencyResolver: menyediakan cara sederhana untuk menyelesaikan layanan Singleton—yaitu, layanan yang instansnya sama dikembalikan setiap kali GetService dipanggil. Layanan sementara sering didaftarkan sebagai pabrik singleton yang akan digunakan untuk membuat instans sementara sesuai permintaan.
- ExecutionStrategyResolver: resolver khusus untuk mengembalikan implementasi IExecutionStrategy.
Alih-alih menggunakan DbProviderServices.AddDependencyResolver juga dimungkinkan untuk mengambil alih DbProviderServices.GetService dan menyelesaikan layanan tambahan secara langsung. Metode ini akan dipanggil ketika EF membutuhkan layanan yang ditentukan oleh jenis tertentu dan, dalam beberapa kasus, untuk kunci tertentu. Metode harus mengembalikan layanan jika dapat, atau mengembalikan null untuk menolak mengembalikan layanan dan sebaliknya memungkinkan kelas lain untuk menyelesaikannya. Misalnya, untuk mengatasi pabrik koneksi default, kode di GetService mungkin terlihat seperti ini:
public override object GetService(Type type, object key)
{
if (type == typeof(IDbConnectionFactory))
{
return new SqlConnectionFactory();
}
return null;
}
Pesanan pendaftaran
Ketika beberapa implementasi DbProviderServices terdaftar dalam file konfigurasi aplikasi, implementasi tersebut akan ditambahkan sebagai penyelesai sekunder dalam urutan yang tercantum. Karena resolver selalu ditambahkan ke bagian atas rantai resolver sekunder, ini berarti bahwa penyedia di akhir daftar akan mendapatkan kesempatan untuk menyelesaikan dependensi sebelum yang lain. (Ini bisa tampak sedikit kontra-intuitif pada awalnya, tetapi masuk akal jika Anda membayangkan mengeluarkan setiap penyedia dari daftar dan menumpuknya di atas penyedia yang ada.)
Pemesanan ini biasanya tidak masalah karena sebagian besar layanan penyedia khusus penyedia dan dikunci oleh nama invarian penyedia. Namun, untuk layanan yang tidak dikunci oleh nama invarian penyedia atau beberapa kunci khusus penyedia lainnya, layanan akan diselesaikan berdasarkan pemesanan ini. Misalnya, jika tidak secara eksplisit diatur secara berbeda di tempat lain, maka pabrik koneksi default akan berasal dari penyedia paling atas dalam rantai.
Pendaftaran file konfigurasi tambahan
Dimungkinkan untuk secara eksplisit mendaftarkan beberapa layanan penyedia tambahan yang dijelaskan di atas langsung dalam file konfigurasi aplikasi. Ketika ini dilakukan, pendaftaran dalam file konfigurasi akan digunakan alih-alih apa pun yang dikembalikan oleh metode GetService dari implementasi DbProviderServices.
Mendaftarkan pabrik koneksi default
Dimulai dengan EF5 paket EntityFramework NuGet secara otomatis mendaftarkan pabrik koneksi SQL Express atau pabrik koneksi LocalDb dalam file konfigurasi.
Contohnya:
<entityFramework>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" >
</entityFramework>
Jenisnya adalah nama jenis yang memenuhi syarat rakitan untuk pabrik koneksi default, yang harus menerapkan IDbConnectionFactory.
Disarankan agar paket NuGet penyedia mengatur pabrik koneksi default dengan cara ini saat diinstal. Lihat Paket NuGet untuk penyedia di bawah ini.
Perubahan penyedia EF6 tambahan
Perubahan penyedia spasial
Penyedia yang mendukung jenis spasial sekarang harus menerapkan beberapa metode tambahan pada kelas yang berasal dari DbSpatialDataReader:
public abstract bool IsGeographyColumn(int ordinal)
public abstract bool IsGeometryColumn(int ordinal)
Ada juga versi asinkron baru dari metode yang ada yang direkomendasikan untuk ditimpa karena implementasi default mendelegasikan ke metode sinkron dan oleh karena itu tidak dijalankan secara asinkron:
public virtual Task<DbGeography> GetGeographyAsync(int ordinal, CancellationToken cancellationToken)
public virtual Task<DbGeometry> GetGeometryAsync(int ordinal, CancellationToken cancellationToken)
Dukungan asli untuk Enumerable.Contains
EF6 memperkenalkan jenis ekspresi baru, DbInExpression, yang ditambahkan untuk mengatasi masalah performa sekeliling penggunaan Enumerable.Contains dalam kueri LINQ. Kelas DbProviderManifest memiliki metode virtual baru, SupportsInExpression, yang dipanggil oleh EF untuk menentukan apakah penyedia menangani jenis ekspresi baru. Untuk kompatibilitas dengan implementasi penyedia yang ada, metode mengembalikan false. Untuk mendapatkan manfaat dari peningkatan ini, penyedia EF6 dapat menambahkan kode untuk menangani DbInExpression dan mengambil alih SupportsInExpression untuk mengembalikan true. Instans DbInExpression dapat dibuat dengan memanggil metode DbExpressionBuilder.In. Instans DbInExpression terdiri dari DbExpression, biasanya mewakili kolom tabel, dan daftar DbConstantExpression untuk diuji kecocokan.
Paket NuGet untuk penyedia
Salah satu cara untuk membuat penyedia EF6 tersedia adalah dengan merilisnya sebagai paket NuGet. Menggunakan paket NuGet memiliki keuntungan berikut:
- Mudah untuk menggunakan NuGet untuk menambahkan pendaftaran penyedia ke file konfigurasi aplikasi
- Perubahan tambahan dapat dilakukan pada file konfigurasi untuk mengatur pabrik koneksi default sehingga koneksi yang dibuat oleh konvensi akan menggunakan penyedia terdaftar
- NuGet menangani penambahan pengalihan pengikatan sehingga penyedia EF6 harus terus bekerja bahkan setelah paket EF baru dirilis
Contohnya adalah paket EntityFramework.SqlServerCompact yang disertakan dalam basis kode sumber terbuka. Paket ini menyediakan templat yang baik untuk membuat paket NuGet penyedia EF.
Perintah PowerShell
Ketika paket EntityFramework NuGet diinstal, paket tersebut mendaftarkan modul PowerShell yang berisi dua perintah yang sangat berguna untuk paket penyedia:
- Add-EFProvider menambahkan entitas baru untuk penyedia dalam file konfigurasi proyek target dan memastikannya berada di akhir daftar penyedia terdaftar.
- Add-EFDefaultConnectionFactory menambahkan atau memperbarui pendaftaran defaultConnectionFactory dalam file konfigurasi proyek target.
Kedua perintah ini mengurus penambahan bagian entityFramework ke file konfigurasi dan menambahkan koleksi penyedia jika perlu.
Ini dimaksudkan agar perintah ini dipanggil dari skrip NuGet install.ps1. Misalnya, install.ps1 untuk penyedia SQL Compact terlihat mirip dengan ini:
param($installPath, $toolsPath, $package, $project)
Add-EFDefaultConnectionFactory $project 'System.Data.Entity.Infrastructure.SqlCeConnectionFactory, EntityFramework' -ConstructorArguments 'System.Data.SqlServerCe.4.0'
Add-EFProvider $project 'System.Data.SqlServerCe.4.0' 'System.Data.Entity.SqlServerCompact.SqlCeProviderServices, EntityFramework.SqlServerCompact'</pre>
Informasi selengkapnya tentang perintah ini dapat diperoleh dengan menggunakan get-help di jendela Package Manager Console.
Penyedia pembungkusan
Penyedia pembungkus adalah penyedia EF dan/atau ADO.NET yang membungkus penyedia yang ada untuk memperluasnya dengan fungsionalitas lain seperti kemampuan pembuatan profil atau pelacakan. Penyedia pembungkus dapat didaftarkan dengan cara normal, tetapi seringkali lebih nyaman untuk mengatur penyedia pembungkus pada runtime dengan mencegat resolusi layanan terkait penyedia. Kejadian statis OnLockingConfiguration pada kelas DbConfiguration dapat digunakan untuk melakukan ini.
OnLockingConfiguration dipanggil setelah EF menentukan di mana semua konfigurasi EF untuk domain aplikasi akan diperoleh tetapi sebelum dikunci untuk digunakan. Pada pengaktifan aplikasi (sebelum EF digunakan) aplikasi harus mendaftarkan penanganan aktivitas untuk peristiwa ini. (Kami sedang mempertimbangkan untuk menambahkan dukungan untuk mendaftarkan handler ini dalam file konfigurasi tetapi ini belum didukung.) Penanganan aktivitas kemudian harus melakukan panggilan ke ReplaceService untuk setiap layanan yang perlu dibungkus.
Misalnya, untuk membungkus IDbConnectionFactory dan DbProviderService, handler sesuatu seperti ini harus didaftarkan:
DbConfiguration.OnLockingConfiguration +=
(_, a) =>
{
a.ReplaceService<DbProviderServices>(
(s, k) => new MyWrappedProviderServices(s));
a.ReplaceService<IDbConnectionFactory>(
(s, k) => new MyWrappedConnectionFactory(s));
};
Layanan yang telah diselesaikan dan sekarang harus dibungkus bersama dengan kunci yang digunakan untuk menyelesaikan layanan diteruskan ke handler. Handler kemudian dapat membungkus layanan ini dan mengganti layanan yang dikembalikan dengan versi yang dibungkus.
Menyelesaikan DbProviderFactory dengan EF
DbProviderFactory adalah salah satu jenis penyedia mendasar yang diperlukan oleh EF seperti yang dijelaskan di bagian Gambaran umum jenis Penyedia di atas. Seperti yang telah disebutkan, Ini bukan jenis dan pendaftaran EF biasanya bukan bagian dari konfigurasi EF, tetapi sebaliknya merupakan pendaftaran penyedia ADO.NET normal dalam file machine.config dan/atau file konfigurasi aplikasi.
Meskipun EF ini masih menggunakan mekanisme resolusi dependensi normalnya saat mencari DbProviderFactory untuk digunakan. Resolver default menggunakan pendaftaran ADO.NET normal dalam file konfigurasi sehingga ini biasanya transparan. Tetapi karena mekanisme resolusi dependensi normal digunakan, itu berarti bahwa IDbDependencyResolver dapat digunakan untuk menyelesaikan DbProviderFactory bahkan ketika pendaftaran ADO.NET normal belum dilakukan.
Menyelesaikan DbProviderFactory dengan cara ini memiliki beberapa implikasi:
- Aplikasi yang menggunakan konfigurasi berbasis kode dapat menambahkan panggilan di kelas DbConfiguration mereka untuk mendaftarkan DbProviderFactory yang sesuai. Ini sangat berguna untuk aplikasi yang tidak ingin (atau tidak dapat) menggunakan konfigurasi berbasis file sama sekali.
- Layanan dapat dibungkus atau diganti menggunakan ReplaceService seperti yang dijelaskan di bagian Penyedia pembungkusan di atas
- Secara teoritis, implementasi DbProviderServices dapat menyelesaikan DbProviderFactory.
Poin penting yang perlu diperhatikan tentang melakukan salah satu hal ini adalah bahwa mereka hanya akan mempengaruhi pencarian DbProviderFactory oleh EF. Kode non-EF lainnya mungkin masih mengharapkan penyedia ADO.NET terdaftar dengan cara normal dan mungkin gagal jika pendaftaran tidak ditemukan. Untuk alasan ini, biasanya lebih baik bagi DbProviderFactory untuk didaftarkan dengan cara ADO.NET normal.
Layanan terkait
Jika EF digunakan untuk mengatasi DbProviderFactory, maka EF juga harus menyelesaikan layanan IProviderInvariantName dan IDbProviderFactoryResolver.
IProviderInvariantName adalah layanan yang digunakan untuk menentukan nama invarian penyedia untuk jenis DbProviderFactory tertentu. Implementasi default layanan ini menggunakan pendaftaran penyedia ADO.NET. Ini berarti bahwa jika penyedia ADO.NET tidak terdaftar dengan cara normal karena DbProviderFactory sedang diselesaikan oleh EF, maka perlu juga untuk menyelesaikan layanan ini. Perhatikan bahwa resolver untuk layanan ini secara otomatis ditambahkan saat menggunakan metode DbConfiguration.SetProviderFactory.
Seperti yang dijelaskan di bagian Gambaran umum jenis Penyedia di atas, IDbProviderFactoryResolver digunakan untuk mendapatkan DbProviderFactory yang benar dari objek DbConnection tertentu. Implementasi default layanan ini saat berjalan pada .NET 4 menggunakan pendaftaran penyedia ADO.NET. Ini berarti bahwa jika penyedia ADO.NET tidak terdaftar dengan cara normal karena DbProviderFactory sedang diselesaikan oleh EF, maka perlu juga untuk menyelesaikan layanan ini.