7.3EF Core与ASP.NET Core集成

7.3EF Core与ASP.NET Core集成

案例:

  1. Nuget安装Microsoft.EntityFrameworkCore.Relational、Microsoft.EntityFrameworkCore.sqlite、Microsoft.EntityFrameworkCore.Tools
  2. 定义Book实体类
public record Book
{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
}
  1. 定义Book配置类
public class BookCon@R_404_6408@ : IEntityTypeCon@R_404_6408@uration<Book>
{
    public void Con@R_404_6408@ure(EntityTypeBuilder<Book> builder)
    {
        builder.ToTable("Books");
    }
}
  1. 加上下文类
public class MyDbContext:DbContext
{
    public DbSet<Book> Books { get; set; }
	//与之前编写的上下文类不同,之前上下文类会重写OnCon@R_404_6408@uring方法,并在里面设置连接字符串
    //但现在要求连接字符串要放在配置中
    //后面会在Program.cs中用依赖注入的方式使用MyDbContext,所以在这里加了一个构造函数
    public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        //设置需要加载的程序集
        //加载当前程序集中所有实现了IEntityTypeCon@R_404_6408@uration接口的类
        modelBuilder.ApplyCon@R_404_6408@urationsFromAssembly(this.GetType().Assembly);
    }
}
  1. 在appsettings.json中增加数据库连接字符的设置
"ConnectionStrings": { "Default": "Data Source=MysqLite.db" }
  1. 在Program.cs中使用依赖注入的方式对上下文的连接字符进行配置
builder.Services.AddDbContext<MyDbContext>(opt => {
    string constr = builder.Con@R_404_6408@uration.GetConnectionString("Default");
    opt.Usesqlite(constr);
});
//如果有多个数据库需要配置,可以直接在后面加,因为AddDbContext是泛型的
  1. 增加控制类
[Route("[controller]/[action]")]
public class TestController : ControllerBase
{
    private readonly MyDbContext dbCtx;
    public TestController(MyDbContext dbCtx)
    {
        this.dbCtx = dbCtx;
    }
    [HttpPost]
    public async Task<IActionResult> Index()
    {
        dbCtx.Add(new Book { Id = Guid.NewGuid(), Name = "ddd", Price = 40 });
        await dbCtx.SaveChangesAsync();
        var book = dbCtx.Books.First();
        return Content(book.ToString());
    }
}
  1. 如果在多项目环境下执行Add-Migration迁移命令的时候,迁移工具发生报错。此时可以使用IDesignTimeDbContextFactory接口来解决。当项目中存在一个该接口的时候,迁移工具会调用实现接口类的CreateDbContext方法获取上下文对象,然后迁移工具使用这个上下文来连接数据库
//该代码只有在开发环境下才会运行
class MyDesignTimeDbContextFactory:IDesignTimeDbContextFactory<MyDbContext>
{
	public MyDbContext CreateDbContext(string[] args)
	{
		DbContextOptionsBuilder<MyDbContext> builder = new();
        //定义了环境变量,其实可以直接使用字符串
		string connStr = Environment.GetEnvironmentvariable("ConnectionStrings:BooksEFCore");
		builder.UsesqlServer(connStr);
		return new MyDbContext(builder.Options);
	}
}
  1. 使用Add-Migration Init、Update-database等命令完成数据库的创建

上下文池

上下文被创建的时候,要执行实体类的配置,所以会消耗较多的资源,所以EF Core提供了AddDbContextPool来注入上下文,对于使用了AddDbContextPool注入的上下文,EF Core会优先从上下文池中获取实例。但是,因为池中的上下文实例会被反复使用,因此没有办法为上下文注入服务。

在项目开发时,建议使用“小上下文”策略,不要把项目中所有的实体放到一个上下文中,而是要将关联性大的实体放到一个上下文中。

如果采用“小上下文”策略,则需要手动注册所有的上下文,批量注册上下文的方法

public static IServiceCollection AddAllDbContexts(this IServiceCollection services, Action<DbContextOptionsBuilder> builder, IEnumerable<Assembly> assemblies)
{
    Type[] types = new Type[] { typeof(IServiceCollection), typeof(Action<DbContextOptionsBuilder>), typeof(ServiceLifetime), typeof(ServiceLifetime) };
    //通过反射获取AddDbContext方法,1代表只有1个泛型参数
    var methodAddDbContext = typeof(EntityFrameworkServiceCollectionExtensions).getmethod("AddDbContext",1,types);
    foreach (var asmToLoad in assemblies)
    {
        //获取非抽象的上下文类
        foreach (var dbCtxType in asmToLoad.GetTypes().Where(t=>!t.IsAbstract && typeof(DbContext).IsAssignableFrom(t)))
        {
            //由于AddDbContext是泛型方法,所以先设定泛型
            var methodGenericAddDbContext = methodAddDbContext.MakeGenericmethod(dbCtxType);
            methodGenericAddDbContext.Invoke(null, new object[] { services, builder, ServiceLifetime.Scoped, ServiceLifetime.Scoped });
        }
    }
    return services;
}

相关文章

显卡天梯图2024最新版,显卡是电脑进行图形处理的重要设备,...
初始化电脑时出现问题怎么办,可以使用win系统的安装介质,连...
todesk远程开机怎么设置,两台电脑要在同一局域网内,然后需...
油猴谷歌插件怎么安装,可以通过谷歌应用商店进行安装,需要...
虚拟内存这个名词想必很多人都听说过,我们在使用电脑的时候...