數據訪問 - EntityFramework集成
- 2022 年 7 月 5 日
- 筆記
- .NET, net, MASA Framework
前言
Masa提供了基於EntityFramework的數據集成,並提供了數據過濾與軟刪除的功能,下面我們將介紹如何使用它?
MasaDbContext入門
- 安裝.Net 6.0
-
新建ASP.NET Core 空項目
Assignment.MasaEntityFramework,並安裝Masa.Contrib.Data.EntityFrameworkCore、Swashbuckle.AspNetCore、Microsoft.EntityFrameworkCore.InMemory、Microsoft.EntityFrameworkCore.Toolsdotnet add package Masa.Contrib.Data.EntityFrameworkCore --version 0.4.0-rc.4 dotnet add package Swashbuckle.AspNetCore --version 6.2.3 dotnet add package Microsoft.EntityFrameworkCore.InMemory --version 6.0.5 dotnet add package Microsoft.EntityFrameworkCore.Tools --version 6.0.5安裝
Swashbuckle.AspNetCore是為了方便通過Swagger來操作服務
安裝Microsoft.EntityFrameworkCore.InMemory是為了方便,因此使用記憶體資料庫,如果需要使用其他資料庫,請自行安裝對應的包
安裝Microsoft.EntityFrameworkCore.Tools是為了使用CodeFirst創建資料庫 -
新建類
Userpublic class User { public int Id { get; set; } public string Name { get; set; } public uint Gender { get; set; } public DateTime BirthDay { get; set; } public DateTime CreationTime { get; set; } public User() { this.CreationTime = DateTime.Now; } } -
新建用戶上下文
UserDbContext.cspublic class UserDbContext : MasaDbContext { public DbSet<User> User { get; set; } public UserDbContext(MasaDbContextOptions options) : base(options) { } }UserDbContext改為繼承MasaDbContext, 並新增一個參數的構造函數,參數類型為MasaDbContextOptions
當項目中存在多個DbContext時,需要改為繼承MasaDbContext<TDbContext>,構造函數參數類型改為MasaDbContext<TDbContext> -
新建類
AddUserRequest作為添加用戶的參數public class AddUserRequest { public string Name { get; set; } public uint Gender { get; set; } public DateTime BirthDay { get; set; } } -
新建類
HostExtensions用於遷移資料庫(使用CodeFirst)public static class HostExtensions { public static void MigrateDbContext<TContext>( this IHost host, Action<TContext, IServiceProvider> seeder) where TContext : DbContext { using (var scope = host.Services.CreateScope()) { var services = scope.ServiceProvider; var context = services.GetRequiredService<TContext>(); context.Database.EnsureCreated(); seeder(context, services); } } } -
修改
Program.cs,新增Swagger支援builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); app.UseSwagger(); app.UseSwaggerUI();
不需要
Swagger可不添加,使用Swagger僅僅是為了測試調用服務,使用Postman或其他的Http工具也可以
-
修改
Program.cs,添加用戶上下文(重點)builder.Services.AddMasaDbContext<UserDbContext>(options => { options.Builder = (_, dbContextOptionsBuilder) => dbContextOptionsBuilder.UseInMemoryDatabase("test") }); -
修改
Program.cs,使項目支援CodeFirstapp.MigrateDbContext<UserDbContext>((context, services) => { });不需要CodeFirst,不支援程式碼生成資料庫可不添加
-
測試
MasaDbContext,修改Program.csapp.MapPost("/add", (UserDbContext dbContext, [FromBody] AddUserRequest request) => { dbContext.Set<User>().Add(new User() { Name = request.Name, Gender = request.Gender, BirthDay = request.BirthDay }); dbContext.SaveChanges(); }); app.MapGet("/list", (UserDbContext dbContext) => { return dbContext.Set<User>().ToList(); });自行運行項目,執行
add後創建一個新的用戶,之後執行list得到一個以上的用戶數據,則證明MasaDbContext使用無誤
如何使用軟刪除
-
選中
Assignment.MasaEntityFramework並安裝Masa.Contrib.Data.Contracts.EFdotnet add package Masa.Contrib.Data.Contracts.EF --version 0.4.0-rc.4 -
修改類
User,並實現ISoftDelete,程式碼改為:public class User : ISoftDelete//重點:改為實現ISoftDelete { public int Id { get; set; } public string Name { get; set; } public uint Gender { get; set; } public DateTime BirthDay { get; set; } public DateTime CreationTime { get; set; } public bool IsDeleted { get; private set; } public User() { this.CreationTime = DateTime.Now; } }增加實現
ISoftDelete,並為IsDeleted屬性添加set支援(可以是private set;) -
修改
Program.cs,並啟用數據過濾builder.Services.AddMasaDbContext<UserDbContext>(options => { options.Builder = (_, dbContextOptionsBuilder) => dbContextOptionsBuilder.UseInMemoryDatabase("test"); options.UseFilter();//啟用數據過濾,完整寫法:options.UseFilter(filterOptions => filterOptions.EnableSoftDelete = true); }); -
測試軟刪除是否成功
-
修改
Program.cs,新增刪除方法app.MapDelete("/delete", (UserDbContext dbContext, int id) => { var user = dbContext.Set<User>().First(u => u.Id == id); dbContext.Set<User>().Remove(user); dbContext.SaveChanges(); });
最後,先調用add方法創建用戶後,之後再調用list方法獲取所有的用戶列表,並取出任意一條id資訊,然後再調用delete方法刪除用戶,最後再調用list方法,查看取出的id是否存在,以此來驗證軟刪除是否有效。
如何臨時禁用軟刪除過濾
默認查詢中會將標記已經被刪除的數據過濾不再進行查詢,但也有一些場景需要查詢所有的數據,此時就需要用到數據過濾IDataFilter
-
新增
All方法用於查詢所有的數據(包含標記已經刪除的數據)app.MapGet("/all", (UserDbContext dbContext, [FromServices] IDataFilter dataFilter) => { //通過DI獲取到IDataFilter,並調用其Disable方法可臨時禁用ISoftDelete條件過濾 using (dataFilter.Disable<ISoftDelete>()) { return dbContext.Set<User>().ToList(); } }); -
重新運行項目,重複執行驗證軟刪除步驟,確保通過
list方法訪問不到數據重複運行驗證軟刪除步驟的原因在於本示例使用的是記憶體資料庫,項目停止後,所有數據都會被清空,重新執行是為了確保數據存在,僅被標記為刪除
-
執行
all方法,獲取所有的數據,查看id所對應的用戶數據是否存在
從配置文件中獲取資料庫連接字元串
-
選中項目
Assignment.MasaEntityFramework,並安裝Masa.Contrib.Data.EntityFrameworkCore.InMemorydotnet add package Masa.Contrib.Data.EntityFrameworkCore.InMemory --version 0.4.0-rc.4根據需要安裝對應資料庫包即可,如:
Masa.Contrib.Data.EntityFrameworkCore.SqlServer(SqlServer)、Masa.Contrib.Data.EntityFrameworkCore.Pomelo.MySql(Pomelo提供的MySql)、Masa.Contrib.Data.EntityFrameworkCore.Oracle(Oracle)等 -
修改
Program.cs,調整添加用戶上下文配置為:builder.Services.AddMasaDbContext<UserDbContext>(options => options.UseInMemoryDatabase().UseFilter()); -
修改
appsettings.json,增加用戶資料庫連接字元串:{ "ConnectionStrings": { "DefaultConnection": "test"//更換為指定的資料庫連接字元串 } } -
修改
Program.cs,新增database方法,驗證當前資料庫是testapp.MapGet("/database", (UserDbContext dbContext) => { var field = typeof(MasaDbContext).GetField("Options", BindingFlags.Public | BindingFlags.Instance | BindingFlags.NonPublic)!; var masaDbContextOptions = field.GetValue(dbContext) as MasaDbContextOptions; foreach (var dbContextOptionsExtension in masaDbContextOptions!.Extensions) { if (dbContextOptionsExtension is InMemoryOptionsExtension memoryOptionsExtension) { return memoryOptionsExtension.StoreName; } } return ""; });
最後訪問//localhost:5002/database,驗證當前的資料庫名稱與修改後的資料庫名稱是否一致

常見問題
- 如何更改默認讀取的配置節點?
-
修改用戶上下文
UserDbContext並增加ConnectionStringName特性:[ConnectionStringName("User")]//自定義節點名 public class UserDbContext : MasaDbContext { public DbSet<User> User { get; set; } public UserDbContext(MasaDbContextOptions options) : base(options) { } } -
修改配置
appsettings.json{ "ConnectionStrings": { "User": "test"//改為從User節點讀取資料庫連接字元串 } }
- 除了從配置文件中獲取,還支援從其他地方獲取資料庫連接字元串嗎?
目前有兩種辦法可以更改資料庫連接字元串。
方法1: 修改Program.cs,並刪除appsettings.json資料庫連接字元串的配置
-
修改
Program.csbuilder.Services.Configure<MasaDbConnectionOptions>(option => { option.ConnectionStrings = new ConnectionStrings(new List<KeyValuePair<string, string>>() { new("User", "test2")//其中鍵為節點名,與ConnectionStringName特性的Name值保持一致即可,如果未指定ConnectionStringName,則應該為DefaultConnection,值為資料庫連接字元串 }); }); -
修改
appsettings.json配置// "ConnectionStrings": { // "User": "test" // }, -
調用
database方法,驗證當前資料庫是否為test2

方法2: 重寫IConnectionStringProvider和IDbConnectionStringProvider的實現並添加到DI中
-
新建類
CustomizeConnectionStringProviderpublic class CustomizeConnectionStringProvider : IConnectionStringProvider { public Task<string> GetConnectionStringAsync(string name = "DefaultConnection") => Task.FromResult (GetConnectionString(name)); public string GetConnectionString(string name = "DefaultConnection") => "test3"; } -
新建類
CustomizeDbConnectionStringProviderpublic class CustomizeDbConnectionStringProvider : IDbConnectionStringProvider { public List<MasaDbContextConfigurationOptions> DbContextOptionsList { get; } = new() { new MasaDbContextConfigurationOptions("test3") }; } -
修改
Program.csbuilder.Services.AddSingleton<IConnectionStringProvider,CustomizeConnectionStringProvider>(); builder.Services.AddSingleton<IDbConnectionStringProvider,CustomizeDbConnectionStringProvider>(); -
調用
database方法,驗證當前資料庫是否為test3

總結
本篇文章主要講解了MasaDbContext的基本用法以及軟刪除、數據過濾如何使用,下篇文章我們會講解一下MasaDbContext是如何實現軟刪除、數據過濾的,以及本篇文章中提到使用資料庫時不指定資料庫鏈接字元串時如何實現的
本章源碼
Assignment05
//github.com/zhenlei520/MasaFramework.Practice
開源地址
MASA.BuildingBlocks://github.com/masastack/MASA.BuildingBlocks
MASA.Contrib://github.com/masastack/MASA.Contrib
MASA.Utils://github.com/masastack/MASA.Utils
MASA.EShop://github.com/masalabs/MASA.EShop
MASA.Blazor://github.com/BlazorComponent/MASA.Blazor
如果你對我們的 MASA Framework 感興趣,無論是程式碼貢獻、使用、提 Issue,歡迎聯繫我們



