前言
Masa
提供了基於EntityFramework
的資料整合,並提供了資料過濾與軟刪除的功能,下面我們將介紹如何使用它?
MasaDbContext入門
- 安裝.Net 6.0
-
新建ASP.NET Core 空專案
Assignment.MasaEntityFramework
,並安裝Masa.Contrib.Data.EntityFrameworkCore
、Swashbuckle.AspNetCore
、Microsoft.EntityFrameworkCore.InMemory
、Microsoft.EntityFrameworkCore.Tools
dotnet 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建立資料庫 -
新建類
User
public 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.cs
public 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.cs
app.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.EF
dotnet 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.InMemory
dotnet 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
方法,驗證當前資料庫是test
app.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 ""; });
最後訪問http://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.cs
builder.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中
-
新建類
CustomizeConnectionStringProvider
public class CustomizeConnectionStringProvider : IConnectionStringProvider { public Task<string> GetConnectionStringAsync(string name = "DefaultConnection") => Task.FromResult (GetConnectionString(name)); public string GetConnectionString(string name = "DefaultConnection") => "test3"; }
-
新建類
CustomizeDbConnectionStringProvider
public class CustomizeDbConnectionStringProvider : IDbConnectionStringProvider { public List<MasaDbContextConfigurationOptions> DbContextOptionsList { get; } = new() { new MasaDbContextConfigurationOptions("test3") }; }
-
修改
Program.cs
builder.Services.AddSingleton<IConnectionStringProvider,CustomizeConnectionStringProvider>(); builder.Services.AddSingleton<IDbConnectionStringProvider,CustomizeDbConnectionStringProvider>();
-
呼叫
database
方法,驗證當前資料庫是否為test3
總結
本篇文章主要講解了MasaDbContext
的基本用法以及軟刪除、資料過濾如何使用,下篇文章我們會講解一下MasaDbContext
是如何實現軟刪除、資料過濾的,以及本篇文章中提到使用資料庫時不指定資料庫連結字串時如何實現的
本章原始碼
Assignment05
https://github.com/zhenlei520/MasaFramework.Practice
開源地址
MASA.BuildingBlocks:https://github.com/masastack/MASA.BuildingBlocks
MASA.Contrib:https://github.com/masastack/MASA.Contrib
MASA.Utils:https://github.com/masastack/MASA.Utils
MASA.EShop:https://github.com/masalabs/MASA.EShop
MASA.Blazor:https://github.com/BlazorComponent/MASA.Blazor
如果你對我們的 MASA Framework 感興趣,無論是程式碼貢獻、使用、提 Issue,歡迎聯絡我們