关于c#:5-数据访问-EntityFramework集成

51次阅读

共计 7393 个字符,预计需要花费 19 分钟才能阅读完成。

前言

Masa提供了基于 EntityFramework 的数据集成,并提供了数据过滤与软删除的性能,上面咱们将介绍如何应用它?

MasaDbContext 入门

  • 装置.Net 6.0
  1. 新建 ASP.NET Core 空我的项目Assignment.MasaEntityFramework,并装置Masa.Contrib.Data.EntityFrameworkCoreSwashbuckle.AspNetCoreMicrosoft.EntityFrameworkCore.InMemoryMicrosoft.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 创立数据库

  2. 新建类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;}
    }
  3. 新建用户上下文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>

  4. 新建类 AddUserRequest 作为增加用户的参数

    public class AddUserRequest
    {public string Name { get; set;}
    
        public uint Gender {get; set;}
    
        public DateTime BirthDay {get; set;}
    }
  5. 新建类 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);
            }
        }
    }
  6. 批改 Program.cs,新增Swagger 反对

    builder.Services.AddEndpointsApiExplorer();
    builder.Services.AddSwaggerGen();
    
    var app = builder.Build();
    
    app.UseSwagger();
    app.UseSwaggerUI();

不须要 Swagger 可不增加,应用 Swagger 仅仅是为了测试调用服务,应用 Postman 或其余的 Http 工具也能够

  1. 批改Program.cs,增加用户上下文(重点)

    builder.Services.AddMasaDbContext<UserDbContext>(options => 
    {options.Builder = (_, dbContextOptionsBuilder) => dbContextOptionsBuilder.UseInMemoryDatabase("test")
    });
  2. 批改Program.cs,使我的项目反对 CodeFirst

    app.MigrateDbContext<UserDbContext>((context, services) =>
    {});

    不须要 CodeFirst,不反对代码生成数据库可不增加

  3. 测试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 应用无误

如何应用软删除

  1. 选中 Assignment.MasaEntityFramework 并装置Masa.Contrib.Data.Contracts.EF

    dotnet add package Masa.Contrib.Data.Contracts.EF --version 0.4.0-rc.4
  2. 批改类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;)

  3. 批改Program.cs,并启用数据过滤

    builder.Services.AddMasaDbContext<UserDbContext>(options =>
    {options.Builder = (_, dbContextOptionsBuilder) => dbContextOptionsBuilder.UseInMemoryDatabase("test");
        options.UseFilter();// 启用数据过滤,残缺写法:options.UseFilter(filterOptions => filterOptions.EnableSoftDelete = true);
    });
  4. 测试软删除是否胜利
  • 批改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

  1. 新增 All 办法用于查问所有的数据(蕴含标记曾经删除的数据)

    app.MapGet("/all", (UserDbContext dbContext, [FromServices] IDataFilter dataFilter) =>
    {
        // 通过 DI 获取到 IDataFilter,并调用其 Disable 办法可长期禁用 ISoftDelete 条件过滤
        using (dataFilter.Disable<ISoftDelete>())
        {return dbContext.Set<User>().ToList();}
    });
  2. 从新运行我的项目,反复执行验证软删除步骤,确保通过 list 办法拜访不到数据

    反复运行验证软删除步骤的起因在于本示例应用的是内存数据库,我的项目进行后,所有数据都会被清空,从新执行是为了确保数据存在,仅被标记为删除

  3. 执行 all 办法,获取所有的数据,查看 id 所对应的用户数据是否存在

从配置文件中获取数据库连贯字符串

  1. 选中我的项目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)等

  2. 批改Program.cs,调整增加用户上下文配置为:

    builder.Services.AddMasaDbContext<UserDbContext>(options => options.UseInMemoryDatabase().UseFilter());
  3. 批改appsettings.json,减少用户数据库连贯字符串:

    {
      "ConnectionStrings": {"DefaultConnection": "test"// 更换为指定的数据库连贯字符串}
    }
  4. 批改 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,验证以后的数据库名称与批改后的数据库名称是否统一

常见问题

  • 如何更改默认读取的配置节点?
  1. 批改用户上下文 UserDbContext 并减少 ConnectionStringName 个性:

    [ConnectionStringName("User")]// 自定义节点名
    public class UserDbContext : MasaDbContext
    {public DbSet<User> User { get; set;}
    
        public UserDbContext(MasaDbContextOptions options) : base(options)
        {}}
  2. 批改配置appsettings.json

    {
      "ConnectionStrings": {"User": "test"// 改为从 User 节点读取数据库连贯字符串}
    }
  • 除了从配置文件中获取,还反对从其余中央获取数据库连贯字符串吗?

目前有两种方法能够更改数据库连贯字符串。

办法 1: 批改 Program.cs,并删除appsettings.json 数据库连贯字符串的配置

  1. 批改Program.cs

    builder.Services.Configure<MasaDbConnectionOptions>(option =>
    {option.ConnectionStrings = new ConnectionStrings(new List<KeyValuePair<string, string>>()
        {new("User", "test2")// 其中键为节点名,与 ConnectionStringName 个性的 Name 值保持一致即可,如果未指定 ConnectionStringName,则应该为 DefaultConnection,值为数据库连贯字符串
        });
    });
  2. 批改 appsettings.json 配置

    //  "ConnectionStrings": {
    //    "User": "test"
    //  },
  3. 调用 database 办法,验证以后数据库是否为test2

办法 2: 重写 IConnectionStringProviderIDbConnectionStringProvider的实现并增加到 DI 中

  1. 新建类CustomizeConnectionStringProvider

    public class CustomizeConnectionStringProvider : IConnectionStringProvider
    {public Task<string> GetConnectionStringAsync(string name = "DefaultConnection") => Task.FromResult    (GetConnectionString(name));
    
        public string GetConnectionString(string name = "DefaultConnection") => "test3";
    }
  2. 新建类CustomizeDbConnectionStringProvider

    public class CustomizeDbConnectionStringProvider : IDbConnectionStringProvider
    {public List<MasaDbContextConfigurationOptions> DbContextOptionsList { get;} = new()
        {new MasaDbContextConfigurationOptions("test3")
        };
    }
  3. 批改Program.cs

    builder.Services.AddSingleton<IConnectionStringProvider,CustomizeConnectionStringProvider>();
    builder.Services.AddSingleton<IDbConnectionStringProvider,CustomizeDbConnectionStringProvider>();
  4. 调用 database 办法,验证以后数据库是否为test3

总结

本篇文章次要解说了 MasaDbContext 的根本用法以及软删除、数据过滤如何应用,下篇文章咱们会解说一下 MasaDbContext 是如何实现软删除、数据过滤的,以及本篇文章中提到应用数据库时不指定数据库链接字符串时如何实现的

本章源码

Assignment05

https://github.com/zhenlei520…

开源地址

MASA.BuildingBlocks:https://github.com/masastack/…

MASA.Contrib:https://github.com/masastack/…

MASA.Utils:https://github.com/masastack/…

MASA.EShop:https://github.com/masalabs/M…

MASA.Blazor:https://github.com/BlazorComp…

如果你对咱们的 MASA Framework 感兴趣,无论是代码奉献、应用、提 Issue,欢送分割咱们

正文完
 0