前言
Entity Framework(EF)Core是輕量化、可擴展、開源和跨平臺版的常用Entity Framework數據訪問技術。
EF Core可用作對象關係映射程序(O/RM),這可以實現以下兩點:
- 使.NET開發人員能夠使用.NET對象處理數據庫。
- 無需再像通常那樣編寫大部分數據訪問代碼。
作爲《乘風破浪,遇見最佳跨平臺跨終端框架.Net Core/.Net生態 - 適用於Entity Framework Core的命令行(CLI)工具集(Dotnet-EF)》以及《乘風破浪,遇見最佳跨平臺跨終端框架.Net Core/.Net生態 - 淺析ASP.NET Core領域驅動設計,通過MediatR中介者模式實現CQRS和領域事件》的姊妹篇,這裏將梳理在Entity Framework Core的廣泛數據庫提供程序支持下,如何實現數據庫的Docker創建和簡單對接。
常見數據庫提供程序
Entity Framework Core可通過名爲數據庫提供程序的插件庫訪問許多不同的數據庫。
數據庫系統 | 配置示例 | NuGet 程序包 |
---|---|---|
SQL Server 或 Azure SQL | .UseSqlServer(connectionString) |
Microsoft.EntityFrameworkCore.SqlServer |
Azure Cosmos DB | .UseCosmos(connectionString, databaseName) |
Microsoft.EntityFrameworkCore.Cosmos |
SQLite | .UseSqlite(connectionString) |
Microsoft.EntityFrameworkCore.Sqlite |
EF Core 內存中數據庫 | .UseInMemoryDatabase(databaseName) |
Microsoft.EntityFrameworkCore.InMemory |
PostgreSQL* | .UseNpgsql(connectionString) |
Npgsql.EntityFrameworkCore.PostgreSQL |
MySQL/MariaDB* | .UseMySql(connectionString) |
Pomelo.EntityFrameworkCore.MySql |
Oracle* | .UseOracle(connectionString) |
Oracle.EntityFrameworkCore |
MySQL | .UseMySQL(connectionString) |
MySql.EntityFrameworkCore |
Docker創建數據庫實例
通過Docker準備PostgreSQL實例
PostgreSQL,通常簡稱爲"Postgres",是一個對象關係型數據庫管理系統(ORDBMS),強調可擴展性和標準符合性。作爲一個數據庫服務器,它的主要功能是安全地存儲數據,並支持最佳實踐,隨後根據其他軟件應用程序的要求進行檢索,無論是同一臺計算機上的軟件還是在網絡上的另一臺計算機上運行的軟件(包括互聯網)。它可以處理從小型單機應用到有許多併發用戶的大型面向互聯網的應用的工作負荷。最近的版本還提供數據庫本身的複製,以保證安全和可擴展性。
PostgreSQL實現了SQL:2011標準的大部分內容,符合ACID標準和事務性(包括大多數DDL語句),使用多版本併發控制(MVCC)避免了鎖定問題,提供了對髒讀和完全序列化的免疫力;使用許多其他數據庫所沒有的索引方法處理複雜的SQL查詢;具有可更新視圖和物化視圖、觸發器、外鍵;支持函數和存儲過程以及其他可擴展性,並有大量由第三方編寫的擴展。除了可以與主要的專有和開源數據庫一起工作外,PostgreSQL還通過其廣泛的標準SQL支持和可用的遷移工具,支持從這些數據庫遷移。如果使用了專有的擴展,通過它的可擴展性,可以通過一些內置的和第三方的開放源碼的兼容性擴展來模擬許多擴展,例如對Oracle的擴展。
準備一個PostgreSQL的Docker實例
docker run -d --name postgres --restart unless-stopped -p 5432:5432 -e "POSTGRES_USER=postgres" -e "POSTGRES_PASSWORD=xxxxxxxxxxxxxx" postgres:14.5
默認的用戶名是postgres
,默認端口是5432
docker exec -it postgres /bin/bash
通過Docker準備MSSQL實例
準備一個MSSQL(Microsoft SQL Server)的Docker實例
docker run -d --name mssql --restart unless-stopped -p 1433:1433 -e "ACCEPT_EULA=Y" -e "MSSQL_SA_PASSWORD=xxxxxxxxxxxxxxxx" mcr.microsoft.com/mssql/server:2022-latest
如果想要運行的是SQL Express版本,還可以追加參數MSSQL_PID
-e "MSSQL_PID=Express"
MSSQL_PID
其實也是用來控制安裝版本的,也和授權有關係
Developer
(默認值)Express
Standard
Enterprise
EnterpriseCore
連接的賬號名是SA
,密碼是自己設置這個,端口是1433
如果忘記密碼,進入容器實例之後,可以查看
docker exec -it mssql /bin/bash
ps -eax
通過Docker準備MYSQL實例
準備一個MYSQL的Docker實例
docker run -d --name mysql --restart unless-stopped -p 3306:3306 -e MYSQL_ROOT_PASSWORD=xxxxxxxxxxxxxxxx mysql:5.7.40
對接示例
建立示例領域和上下文
領域模型
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public string Title { get; set; }
public string Name { get; set; }
public List<Post> Posts { get; } = new List<Post>();
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogId { get; set; }
public Blog Blog { get; set; }
}
上下文
public class BloggingContext : DbContext
{
public BloggingContext(DbContextOptions<BloggingContext> options)
: base(options)
{
}
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
建立示例項目(SQLite)
依賴包
https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Sqlite
dotnet add package Microsoft.EntityFrameworkCore.Sqlite
如果是
Net Core 3.1
項目,最新的版本無法兼容,可以追加版本號參數--version 5.0.17
。
建立示例DbContext
public class BloggingContext : DbContext
{
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
public string DbPath { get; }
public BloggingContext()
{
var folder = Environment.SpecialFolder.LocalApplicationData;
var path = Environment.GetFolderPath(folder);
DbPath = System.IO.Path.Join(path, "blogging.db");
}
// The following configures EF to create a Sqlite database file in the
// special "local" folder for your platform.
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options.UseSqlite($"Data Source={DbPath}");
}
使用它
using (var db = new BloggingContext())
{
Console.WriteLine("Ensure Database Created");
db.Database.EnsureCreated();
Console.WriteLine($"DbPath:{db.DbPath}");
Console.WriteLine("Inserting a new blog");
var blog = new Blog
{
BlogId = 16839191,
Url = "https://www.cnblogs.com/taylorshi/p/16839191.html"
};
db.Add(blog);
db.SaveChanges();
}
Console.WriteLine("Hello World!");
前面使用的是在DbContext
內部去定義位置和連接字符串,實際上,可以從外面傳進去。
public class PosttingContext : DbContext
{
public PosttingContext(DbContextOptions<PosttingContext> options)
: base(options)
{
}
public DbSet<Blog> Blogs { get; set; }
public DbSet<Post> Posts { get; set; }
}
這裏需要構建一個公開的構造函數,通過這個入口就能將上下文配置從外部傳進來。
我們試着修改下使用方式
static void Main(string[] args)
{
var folder = Environment.SpecialFolder.MyDocuments;
var path = Environment.GetFolderPath(folder);
var DbPath = System.IO.Path.Join(path, "EFSqliteConsole.db");
var services = new ServiceCollection();
services.AddDbContext<BloggingContext>(opt => opt.UseSqlite($"Data Source={DbPath}"));
using (var scope = services.BuildServiceProvider().CreateScope())
{
var context = scope.ServiceProvider.GetService<BloggingContext>();
//context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var blog = new Blog
{
BlogId = new Random(16839191).Next(),
Url = "https://www.cnblogs.com/taylorshi/p/16843914.html"
};
context.Add(blog);
context.SaveChanges();
var blogs = context.Blogs.ToList();
if (blogs.Any())
{
}
}
Console.ReadKey();
}
建立示例項目(SQLServer)
依賴包
https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.SqlServer
dotnet add package Microsoft.EntityFrameworkCore.SqlServer
如果是
Net Core 3.1
項目,最新的版本無法兼容,可以追加版本號參數--version 5.0.17
。
static void Main(string[] args)
{
var connectionString = "Server=tcp:localhost,1433;Database=TeslaOrder.EFSqlServerConsole;User Id=sa;Password=beE#Yahlj!Sdgj6x;";
var services = new ServiceCollection();
services.AddDbContext<BloggingContext>(opt => opt.UseSqlServer(connectionString));
using (var scope = services.BuildServiceProvider().CreateScope())
{
var context = scope.ServiceProvider.GetService<BloggingContext>();
//context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var blog = new Blog
{
Url = "https://www.cnblogs.com/taylorshi/p/16843914.html"
};
context.Add(blog);
context.SaveChanges();
var blogs = context.Blogs.ToList();
if (blogs.Any())
{
}
}
Console.ReadKey();
}
建立示例項目(InMemory)
依賴包
https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.InMemory
dotnet add package Microsoft.EntityFrameworkCore.InMemory
如果是
Net Core 3.1
項目,最新的版本無法兼容,可以追加版本號參數--version 5.0.17
。
static void Main(string[] args)
{
var databaseName = "EFInMeoryConsole";
var services = new ServiceCollection();
services.AddDbContext<BloggingContext>(opt => opt.UseInMemoryDatabase(databaseName));
using (var scope = services.BuildServiceProvider().CreateScope())
{
var context = scope.ServiceProvider.GetService<BloggingContext>();
//context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var blog = new Blog
{
Url = "https://www.cnblogs.com/taylorshi/p/16843914.html"
};
context.Add(blog);
context.SaveChanges();
var blogs = context.Blogs.ToList();
if (blogs.Any())
{
}
}
Console.ReadKey();
}
建立示例項目(Azure Cosmos DB)
依賴包
https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Cosmos
dotnet add package Microsoft.EntityFrameworkCore.Cosmos
如果是
Net Core 3.1
項目,最新的版本無法兼容,可以追加版本號參數--version 5.0.17
。
static void Main(string[] args)
{
var connectionString = "AccountEndpoint=https://xxxxxxx.documents.azure.com:443/;AccountKey=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxlUFYU9lbHgWw3FTLNzQB1IDm1DZ5VGHZQwACDbS4IgGA==;";
var databaseName = "EFCosmosConsole";
var services = new ServiceCollection();
services.AddDbContext<BloggingContext>(opt => opt.UseCosmos(connectionString, databaseName));
using (var scope = services.BuildServiceProvider().CreateScope())
{
var context = scope.ServiceProvider.GetService<BloggingContext>();
//context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var blog = new Blog
{
BlogId = new Random(99999).Next(),
Url = "https://www.cnblogs.com/taylorshi/p/16843914.html"
};
context.Add(blog);
context.SaveChanges();
var blogs = context.Blogs.ToList();
if (blogs.Any())
{
}
}
Console.ReadKey();
}
建立示例項目(PostgreSQL)
依賴包
https://www.nuget.org/packages/Npgsql.EntityFrameworkCore.PostgreSQL
dotnet add package Npgsql.EntityFrameworkCore.PostgreSQL
如果是
Net Core 3.1
項目,最新的版本無法兼容,可以追加版本號參數--version 5.0.10
。
static void Main(string[] args)
{
var connectionString = "Host=localhost;Port=5432;Database=EFPostgreSQLConsole;Username=postgres;Password=xxxxxxxxxxxxxxxxxxxxx;Pooling=true;";
var services = new ServiceCollection();
services.AddDbContext<BloggingContext>(opt => opt.UseNpgsql(connectionString));
using (var scope = services.BuildServiceProvider().CreateScope())
{
var context = scope.ServiceProvider.GetService<BloggingContext>();
//context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var blog = new Blog
{
Url = "https://www.cnblogs.com/taylorshi/p/16843914.html"
};
context.Add(blog);
context.SaveChanges();
var blogs = context.Blogs.ToList();
if (blogs.Any())
{
}
}
Console.ReadKey();
}
建立示例項目(MySQL)
依賴包
https://www.nuget.org/packages/Pomelo.EntityFrameworkCore.MySql
dotnet add package Pomelo.EntityFrameworkCore.MySql
如果是
Net Core 3.1
項目,最新的版本無法兼容,可以追加版本號參數--version 5.0.4
。
查看MYSQL版本,構建MySqlServerVersion
對象,如果是
select @@version as version;
static void Main(string[] args)
{
var connectionString = "server=localhost;port=16000;user=root;password=xxxxxxxxxxxxxx;database=EFMySQLPomeloConsole;charset=utf8mb4;ConnectionReset=false;Min Pool Size=10;Max Pool Size=200;";
var serverVersion = new MySqlServerVersion(new Version(5, 7, 40));
var services = new ServiceCollection();
services.AddDbContext<BloggingContext>(opt => opt.UseMySql(connectionString, serverVersion));
using (var scope = services.BuildServiceProvider().CreateScope())
{
var context = scope.ServiceProvider.GetService<BloggingContext>();
//context.Database.EnsureDeleted();
context.Database.EnsureCreated();
var blog = new Blog
{
Url = "https://www.cnblogs.com/taylorshi/p/16843914.html"
};
context.Add(blog);
context.SaveChanges();
var blogs = context.Blogs.ToList();
if (blogs.Any())
{
}
}
Console.ReadKey();
}
這裏還可以配置重試機制
services.AddDbContext<BloggingContext>(opt =>
{
opt.UseMySql
(
connectionString,
serverVersion,
options => options.EnableRetryOnFailure
(
maxRetryCount: 3,
maxRetryDelay: System.TimeSpan.FromSeconds(10),
errorNumbersToAdd: new List<int> { 0 }
)
);
});
https://dev.mysql.com/doc/mysql-errors/5.7/en/server-error-reference.html
EnableRetryOnFailure
方法中errorNumbersToAdd
參數是用來設置錯誤代碼的,只有設置了錯誤代碼的錯誤,纔會觸發重試。獲取錯誤代碼的方法有很多種,通過異常信息進行獲取,比如,使用MySql數據時,觸發的異常類型是MySqlException
,此類的Number屬性的值EnableRetryOnFailure
方法所需要的Number
簡單數據庫日誌記錄
默認情況下Entity Framework Core都可以和Microsoft.Extensions.Logging很好的配合,只需要在平時我們配置數據庫的後面追加相關策略即可。
根據日誌級別輸出到控制檯
services.AddDbContext<BloggingContext>(opt =>
opt.UseMySql(connectionString, serverVersion)
// 日誌輸出到控制檯
.LogTo(Console.WriteLine, LogLevel.Information)
);
根據日誌類別來輸出到控制檯
services.AddDbContext<BloggingContext>(opt =>
opt.UseMySql(connectionString, serverVersion)
// 日誌輸出到控制檯
.LogTo(Console.WriteLine, new[] { DbLoggerCategory.Database.Name })
);
系統會將每條日誌消息分配到一個已命名的分層記錄器類別,這些類別包括
類別 | 消息 |
---|---|
Microsoft.EntityFrameworkCore | 所有 EF Core 消息 |
Microsoft.EntityFrameworkCore.Database | 所有數據庫交互 |
Microsoft.EntityFrameworkCore.Database.Connection | 使用數據庫連接 |
Microsoft.EntityFrameworkCore.Database.Command | 使用數據庫命令 |
Microsoft.EntityFrameworkCore.Database.Transaction | 使用數據庫事務 |
Microsoft.EntityFrameworkCore.Update | 正在保存實體,不包括數據庫交互 |
Microsoft.EntityFrameworkCore.Model | 所有模型和元數據交互 |
Microsoft.EntityFrameworkCore.Model.Validation | 模型驗證 |
Microsoft.EntityFrameworkCore.Query | 查詢,不包括數據庫交互 |
Microsoft.EntityFrameworkCore.Infrastructure | 常規事件,例如上下文創建 |
Microsoft.EntityFrameworkCore.Scaffolding | 數據庫反向工程 |
Microsoft.EntityFrameworkCore.Migrations | 遷移 |
Microsoft.EntityFrameworkCore.ChangeTracking | 更改跟蹤交互 |
日誌輸出記錄敏感數據
services.AddDbContext<BloggingContext>(opt =>
opt.UseMySql(connectionString, serverVersion)
// 日誌輸出記錄敏感數據
.EnableSensitiveDataLogging()
);
日誌輸出記錄詳細異常
services.AddDbContext<BloggingContext>(opt =>
opt.UseMySql(connectionString, serverVersion)
// 日誌輸出記錄詳細異常
.EnableDetailedErrors()
);
啓用上下文池提高吞吐
DbContext對用於和數據庫打交道的上下文,創建和釋放它在高性能場景下仍然存在可優化空間,可通過AddDbContextPool
來替代AddDbContext
以便啓用上下文池。
services.AddDbContextPool<BloggingContext>(opt => opt.UseMySql(connectionString, serverVersion));
需要注意的是,AddDbContextPool
的最大保留實例數(>= EFCore 6.0 默認值爲1024
,< EFCore 6.0 默認值爲128
),一旦超過這個保留數,將不再緩存新的上下文實例,會恢復到非池模式進行創建。
但是如果上下文池的連接數超過了數據庫連接池的連接數時,就可能引發數據庫連接池連接數超限的問題,爲了避免這個問題,要麼我們將上下文池的默認值改小,要麼在數據庫連接字符串那裏把數據庫連接池的值改大。
對MYSQL和MSServer而言,數據庫連接池最小值默認是0,最大值默認是100
var connectionString = "........;Min Pool Size=10;Max Pool Size=200;";
查看MYSQL的查詢連接數
show processlist
使用加密Sqlite+EfCore
Sqlite的免費版默認是不支持加密的.
已知的Sqlite加密工具有
SQLCipher是一個開源的,基於免費版SQLite的加密數據庫。它採用256-bit AES進行加密,主要的接口和SQLite相同,另外增加了一些加解密相關的接口。
依賴包
https://www.nuget.org/packages/SQLitePCLRaw.bundle_e_sqlcipher
dotnet add package Microsoft.Data.Sqlite.Core --version 5.0.17
dotnet add package SQLitePCLRaw.bundle_e_sqlcipher --version 2.1.2
使用SqliteConnectionStringBuilder
來創建帶密碼的SQLite數據庫
internal class Program
{
static void Main(string[] args)
{
var folder = Environment.SpecialFolder.MyDocuments;
var path = Environment.GetFolderPath(folder);
var dbPath = System.IO.Path.Join(path, "postting.db");
var baseConnectionString = $"Data Source={dbPath}";
var oldPassword = "xxxxxxxxxxxxxxxx";
var connectionString = new SqliteConnectionStringBuilder(baseConnectionString)
{
Mode = SqliteOpenMode.ReadWriteCreate,
Password = oldPassword
}.ToString();
// 設置密碼
using (SqliteConnection connection = new SqliteConnection(connectionString))
{
connection.Open();
using (var cmd = connection.CreateCommand())
{
cmd.CommandText = @"CREATE TABLE Users (
ID INTEGER PRIMARY KEY AUTOINCREMENT
);";
cmd.ExecuteNonQuery();
}
}
Console.ReadKey();
}
}
這裏使用SqliteConnectionStringBuilder
來構建一個帶有密碼的Sqlite連接字符串對象,然後使用Microsoft.Data.Sqlite
名下的SqliteConnection
來創建連接,特別注意的是,創建完之後,插入一張空表,不然可能會還是未加密的。
Sqlite可以通過PRAGMA
命令來進一步修改密碼
internal class Program
{
static void Main(string[] args)
{
var folder = Environment.SpecialFolder.MyDocuments;
var path = Environment.GetFolderPath(folder);
var dbPath = System.IO.Path.Join(path, "postting.db");
var baseConnectionString = $"Data Source={dbPath}";
var oldPassword = "BkBqwG3ps25qQExj";
var connectionString = new SqliteConnectionStringBuilder(baseConnectionString)
{
Mode = SqliteOpenMode.ReadWriteCreate,
Password = oldPassword
}.ToString();
// 修改密碼
var newPassword = "BkBqwG3ps25qQEx";
using (SqliteConnection connection = new SqliteConnection(connectionString))
{
connection.Open();
using (var command = connection.CreateCommand())
{
command.CommandText = "SELECT quote($newPassword);";
command.Parameters.AddWithValue("$newPassword", newPassword);
var quotedNewPassword = command.ExecuteScalar() as string;
command.CommandText = "PRAGMA rekey = " + quotedNewPassword;
command.Parameters.Clear();
command.ExecuteNonQuery();
}
}
Console.ReadKey();
}
}
基於EFCore來使用帶有密碼(SQLCipher加密機制)的Sqlite
依賴包
https://www.nuget.org/packages/Microsoft.EntityFrameworkCore.Sqlite
https://www.nuget.org/packages/SQLitePCLRaw.bundle_e_sqlcipher
dotnet add package Microsoft.EntityFrameworkCore.Sqlite --version 5.0.17
dotnet add package SQLitePCLRaw.bundle_e_sqlcipher --version 2.1.2
internal class Program
{
static void Main(string[] args)
{
var folder = Environment.SpecialFolder.MyDocuments;
var path = Environment.GetFolderPath(folder);
var dbPath = System.IO.Path.Join(path, "postting.db");
var dbPassword = "BkBqwG3ps25qQExj";
var connectionString = $"Data Source={dbPath};Password={dbPassword};";
var services = new ServiceCollection();
services.AddDbContext<PosttingContext>(opt => opt.UseSqlite(connectionString));
using (var scope = services.BuildServiceProvider().CreateScope())
{
var context = scope.ServiceProvider.GetService<PosttingContext>();
context.Database.EnsureCreated();
var blog = new Blog
{
BlogId = new Random(16839191).Next(),
Url = "https://www.cnblogs.com/taylorshi/p/16839191.html"
};
context.Add(blog);
context.SaveChanges();
var blogs = context.Blogs.ToList();
if (blogs.Any())
{
}
}
Console.ReadKey();
}
}
如何在已激活後的Navicat 16中打開它呢?
先運行或者編譯程序,前往bin\Debug\netcoreapp3.1\runtimes\win-x64\native
目錄
將e_sqlcipher.dll
改名成sqlite3.dll
,然後將改名後的sqlite3.dll
複製替換C:\Program Files\PremiumSoft\Navicat Premium 16
目錄下的sqlite3.dll
即可
接下來新建SQLite 3的連接
並在高級中填寫密碼
就可以打開了。
參考
- Entity Framework Core
- EF Core 異步編程注意要點
- netcore3.1連接MySQL時報錯: Method ‘Create‘ in type ... does not have an implementation的解決辦法
- .net core 註冊多個dbcontext注意事項
- 好大一個坑: EF Core 異步讀取大字符串字段比同步慢100多倍
- Entity Framework Core的貼心:優雅處理帶默認值的數據庫字段
- Entity Framework Core的坑:Skip/Take放在Select之前造成Include的實體全表查詢
- 被Entity Framework Core的細節改進震撼了一下
- 對Entity Framework Core的一次誤會:實體狀態不跟蹤
- 使用Entity Framework Core需要注意的一個全表查詢問題
- EF(Entity Framework)多對多關係下用LINQ實現"NOT IN"查詢
- Why do we need to set Min pool size in ConnectionString
- EFCore 使用DbContextPool提高EfCore查詢性能
- EF Core 小坑:DbContextPool 會引起數據庫連接池連接耗盡
- TargetParameterCountException when enumerating through properties of string
- efcore技巧貼-也許有你不知道的使用技巧
- SqlConnectionStringBuilder類
- DbContext生存期、配置和初始化
- 加密
- .NET+Sqlite如何支持加密
- Microsoft.Data.Sqlite連接字符串
- FreeSql.Provider.SqliteCore如何加密
- 關於SQLite加密,看這篇就夠了
- 再見收費的Navicat!操作所有數據庫就靠它了!
- Navicat Premium 16 永久破解激活
- https://dbeaver.io
- Navicat.zip
- EFCore 使用Sqlite(帶加密)
- Password protected SQLite with Entity Framework Core
- The DbContext of type cannot be pooled because it does not have a single public constructor accepting a single parameter of type DbContextOptions
- EF Core Azure Cosmos DB Provider
- 數據庫提供程序
- Npgsql Entity Framework Core Provider
- EntityFramework Core使用PostgreSQL
- MySQL .NET Connection String Options
- Pomelo.EntityFrameworkCore.MySql-Configuration Options
- Entity Framework Core-簡單的日誌記錄
- .Net EntityFramework連接Mysql連接池配置
- Chapter 2 Server Error Message Reference
- 使用 EF Core 的 EnableRetryOnFailure 解決短暫的數據庫連接失敗問題
- Consider enabling transient error resiliency by adding 'EnableRetryOnFailure()' to the 'UseMySql' call