foreword
Masa
Provides EntityFramework
data integration based on data, and provides functions of data filtering and soft deletion. Below we will introduce how to use it?
Getting Started with MasaDbContext
- Install .Net 6.0
-
Create a new ASP.NET Core empty project
Assignment.MasaEntityFramework
and installMasa.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
The installation
Swashbuckle.AspNetCore
is for the convenienceSwagger
of operating the service installationMicrosoft.EntityFrameworkCore.InMemory
is for the convenience, so use the in-memory database, if you need to use other databases, please install the corresponding package by yourself The installationMicrosoft.EntityFrameworkCore.Tools
is to use CodeFirst to create a database -
new class
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; } }
-
New user context
UserDbContext.cs
public class UserDbContext : MasaDbContext { public DbSet<User> User { get; set; } public UserDbContext(MasaDbContextOptions options) : base(options) { } }
UserDbContext
Change to inheritanceMasaDbContext
, and add a constructor with a parameter, the parameter type isMasaDbContextOptions
When there are multiple DbContexts in the project, it needs to be changed to inheritanceMasaDbContext<TDbContext>
, and the parameter type of the constructor is changed toMasaDbContext<TDbContext>
-
Create a new class
AddUserRequest
as a parameter to add a userpublic class AddUserRequest { public string Name { get; set; } public uint Gender { get; set; } public DateTime BirthDay { get; set; } }
-
New class
HostExtensions
for migrating database (using 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); } } }
-
Modify
Program.cs
, addSwagger
supportbuilder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); var app = builder.Build(); app.UseSwagger(); app.UseSwaggerUI();
No need
Swagger
to add, use Swagger just to test the calling service,Postman
or other Http tools can also be used
-
Modify
Program.cs
, add user context (emphasis)builder.Services.AddMasaDbContext<UserDbContext>(options => { options.Builder = (_, dbContextOptionsBuilder) => dbContextOptionsBuilder.UseInMemoryDatabase("test") });
-
Modified
Program.cs
to make the project support CodeFirstapp.MigrateDbContext<UserDbContext>((context, services) => { });
CodeFirst is not required, and it is not necessary to add a database that does not support code generation
-
test
MasaDbContext
, modifyProgram.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(); });
Run the project by yourself
add
, create a new user after execution, and then executelist
to get more than one user data, which proves that theMasaDbContext
use is correct
How to use soft delete
-
select
Assignment.MasaEntityFramework
and installMasa.Contrib.Data.Contracts.EF
dotnet add package Masa.Contrib.Data.Contracts.EF --version 0.4.0-rc.4
-
Modify the class
User
and implementISoftDelete
, the code is changed to: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; } }
Add implementation
ISoftDelete
, andIsDeleted
add set support for properties (can be private set;) -
Modify
Program.cs
and enable data filteringbuilder.Services.AddMasaDbContext<UserDbContext>(options => { options.Builder = (_, dbContextOptionsBuilder) => dbContextOptionsBuilder.UseInMemoryDatabase("test"); options.UseFilter();//启用数据过滤,完整写法:options.UseFilter(filterOptions => filterOptions.EnableSoftDelete = true); });
-
Test if the soft delete was successful
-
Modify
Program.cs
, add delete methodapp.MapDelete("/delete", (UserDbContext dbContext, int id) => { var user = dbContext.Set<User>().First(u => u.Id == id); dbContext.Set<User>().Remove(user); dbContext.SaveChanges(); });
Finally, first call the add
method to create a user, then call list
the method to obtain a list of all users, and retrieve any id information, then call the delete
method to delete the user, and finally call list
the method to check whether the retrieved id exists, so as to verify the software. Whether the deletion is valid.
How to temporarily disable soft delete filtering
In the default query, the data that has been marked deleted will be filtered and no longer queried, but there are also some scenarios where all data needs to be queried, in which case data filtering is requiredIDataFilter
-
Added
All
method for querying all data (including data marked for deletion)app.MapGet("/all", (UserDbContext dbContext, [FromServices] IDataFilter dataFilter) => { //通过DI获取到IDataFilter,并调用其Disable方法可临时禁用ISoftDelete条件过滤 using (dataFilter.Disable<ISoftDelete>()) { return dbContext.Set<User>().ToList(); } });
-
Rerun the project and repeat the verify soft delete steps to ensure that the
list
data is not accessible through the methodThe reason for running the verification soft delete step repeatedly is that this example uses an in-memory database. After the project is stopped, all data will be emptied. The re-execution is to ensure that the data exists and is only marked for deletion.
-
Execute the
all
method, get all the data, and check whether the user data corresponding to the id exists
Get database connection string from configuration file
-
Select the project
Assignment.MasaEntityFramework
and installMasa.Contrib.Data.EntityFrameworkCore.InMemory
dotnet add package Masa.Contrib.Data.EntityFrameworkCore.InMemory --version 0.4.0-rc.4
Install the corresponding database package as needed, such as:
Masa.Contrib.Data.EntityFrameworkCore.SqlServer
(SqlServer),Masa.Contrib.Data.EntityFrameworkCore.Pomelo.MySql
(MySql provided by Pomelo),Masa.Contrib.Data.EntityFrameworkCore.Oracle
(Oracle), etc. -
Modify
Program.cs
, adjust the add user context configuration to:builder.Services.AddMasaDbContext<UserDbContext>(options => options.UseInMemoryDatabase().UseFilter());
-
Modify
appsettings.json
, increase the user database connection string:{ "ConnectionStrings": { "DefaultConnection": "test"//更换为指定的数据库连接字符串 } }
-
Modify
Program.cs
, adddatabase
a method, verify that the current database istest
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 ""; });
Last visit http://localhost:5002/database
to verify whether the current database name is the same as the modified database name
common problem
- How to change the default read configuration node?
-
Modify the user context
UserDbContext
and addConnectionStringName
features:[ConnectionStringName("User")]//自定义节点名 public class UserDbContext : MasaDbContext { public DbSet<User> User { get; set; } public UserDbContext(MasaDbContextOptions options) : base(options) { } }
-
Change setting
appsettings.json
{ "ConnectionStrings": { "User": "test"//改为从User节点读取数据库连接字符串 } }
- Is it supported to get the database connection string from somewhere other than from the config file?
There are currently two ways to change the database connection string.
Method 1: Modify Program.cs
and delete appsettings.json
the configuration of the database connection string
-
Revise
Program.cs
builder.Services.Configure<MasaDbConnectionOptions>(option => { option.ConnectionStrings = new ConnectionStrings(new List<KeyValuePair<string, string>>() { new("User", "test2")//其中键为节点名,与ConnectionStringName特性的Name值保持一致即可,如果未指定ConnectionStringName,则应该为DefaultConnection,值为数据库连接字符串 }); });
-
Modify
appsettings.json
configuration// "ConnectionStrings": { // "User": "test" // },
-
Call
database
the method to verify whether the current database istest2
Method 2: Override the implementation of IConnectionStringProvider
sum IDbConnectionStringProvider
and add to DI
-
new class
CustomizeConnectionStringProvider
public class CustomizeConnectionStringProvider : IConnectionStringProvider { public Task<string> GetConnectionStringAsync(string name = "DefaultConnection") => Task.FromResult (GetConnectionString(name)); public string GetConnectionString(string name = "DefaultConnection") => "test3"; }
-
new class
CustomizeDbConnectionStringProvider
public class CustomizeDbConnectionStringProvider : IDbConnectionStringProvider { public List<MasaDbContextConfigurationOptions> DbContextOptionsList { get; } = new() { new MasaDbContextConfigurationOptions("test3") }; }
-
Revise
Program.cs
builder.Services.AddSingleton<IConnectionStringProvider,CustomizeConnectionStringProvider>(); builder.Services.AddSingleton<IDbConnectionStringProvider,CustomizeDbConnectionStringProvider>();
-
Call
database
the method to verify whether the current database istest3
Summarize
This article mainly explains the MasaDbContext
basic usage and how to use soft delete and data filtering. In the next article, we will explain MasaDbContext
how to implement soft delete and data filtering, and how to use the database without specifying the database link character mentioned in this article. How is the string time implemented?
Source code of this chapter
Assignment05
https://github.com/zhenlei520/MasaFramework.Practice
open source address
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
If you are interested in our MASA Framework, whether it is code contribution, use, issue, please contact us