ASP.NET Core与EF Core的集成

发布于:2025-02-10 ⋅ 阅读:(45) ⋅ 点赞:(0)

目录

分层项目中EF Core的用法

数据库的配置

数据库迁移

步骤汇总

注意:

批量注册上下文


分层项目中EF Core的用法

  1. 创建一个.NET类库项目BooksEFCore,放实体等类。
  2. NuGet:Microsoft.EntityFrameworkCore.Relational
  3. BooksEFCore中增加实体类Book和配置类。

数据库的配置

  1. 上下文类MyDbContext :为什么正式项目中最好不要在MyDbContext写数据库配置(连接不同的DB甚至不同类型的DB)。尽量数据库配置的代码写到ASP.NET Core项目中。不重写OnConfiguring方法,而是为MyDbContext类的构造方法增加DbContextOptions<MyDbContext>参数。在ASP.NET Core项目对DbContextOptions的配置。
  2. 创建ASP.NET Core项目,添加对“BooksEFCore”项目的引用。NuGet安装Microsoft.EntityFrameworkCore.SqlServer。
  3. 配置文件、配置代码等放到ASP.NET Core项目中。
MyDbContext:
public class MyDbContext : DbContext
{
    public DbSet<Book> Books { get; set; }
    public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
    {
    }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);
        modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
    }
}

secrets.json:
{
  "ConnStr": "Data Source=.;Initial Catalog=demo1;Integrated Security=SSPI;TrustServerCertificate=true;"
}

Program.cs:
builder.Services.AddDbContext<MyDbContext>(opt =>
{
    string connStr = builder.Configuration.GetSection("ConnStr").Value;
    opt.UseSqlServer(connStr);
});

Controller:
private readonly MyDbContext dbCtx;
public TestController(MyDbContext dbCtx)
{
    this.dbCtx = dbCtx;
}

数据库迁移

  1. 不用研究多项目中Add-Migration的细节。实用的方案:编写实现IDesignTimeDbContextFactory接口的类,把配置放到里面,反正是开发环境用而已。
  2. 可以把连接字符串配置到环境变量中,不过MyDesignTimeDbContextFactory中很难使用IConfiguration来读取配置系统,可以直接用Environment.GetEnvironmentVariable() 读取环境变量。
  3. 数据库迁移脚本要生成到BooksEFCore中,因此为这个项目安装Microsoft.EntityFrameworkCore.Tools、Microsoft.EntityFrameworkCore.SqlServer。然后把BooksEFCore设置为启动项目,并且在【程序包管理器控制台】中也选中BooksEFCore项目后,执行Add-Migration和Update-Database
internal class MyDesignTimeDbContextFactory : IDesignTimeDbContextFactory<MyDbContext>
{
    //开发时(Add-Migration、Update-Database等)运行的数据库上下文工厂
    public MyDbContext CreateDbContext(string[] args)
    {
        DbContextOptionsBuilder<MyDbContext> optionsBuilder = new DbContextOptionsBuilder<MyDbContext>();
        string connStr = Environment.GetEnvironmentVariable("ConnStr");
        optionsBuilder.UseSqlServer(connStr);
        MyDbContext dbCtx = new MyDbContext(optionsBuilder.Options);
        return dbCtx;
    }
}

步骤汇总

  1. 建类库项目,放实体类、DbContext、配置类等;DbContext中不配置数据库连接,而是为DbContext增加一个DbContextOptions类型的构造函数。
  2. EFCore项目安装对应数据库的EFCore Provider
  3. asp.net core项目引用EFCore项目,并且通过AddDbContext来注入DbContext及对DbContext进行配置。
  4. Controller中就可以注入DbContext类使用了。
  5. 让开发环境的Add-Migration知道连接哪个数据库,在EFCore项目中创建一个实现了IDesignTimeDbContextFactory的类。并且在CreateDbContext返回一个连接开发数据库的DbContext。
    如果不在乎连接字符串被上传到Git,就可以把连接字符串直接写死到CreateDbContext;如果在乎,那么CreateDbContext里面很难读取到VS中通过简单的方法设置的环境变量,所以必须把连接字符串配置到Windows的正式的环境变量中,然后再 Environment.GetEnvironmentVariable读取。
  6. 正常执行Add-Migration、Update-Database迁移就行了。需要把EFCore项目设置为启动项目,并且在【程序包管理器控制台】中也要选中EFCore项目,并且安装Microsoft.EntityFrameworkCore.SqlServer、Microsoft.EntityFrameworkCore.Tools

注意:

配置完环境变量需重启VS

批量注册上下文

如果项目采用小上下文策略,在项目中可能就存在多个上下文类,需要手动调用AddDbContext方法注册,如果上下文连接的是同一个数据库,可以采用反射的方式扫描程序集中所有的上下文,然后为它们逐个调用AddDbContext注册。

Add-Migration xxx -Context DbContext名

Update-Database -Context DbContext名

Install-Package Zack.Infrastructure

//var asms=new Assembly[] {Assembly.Load("EFCoreBooks") };
var asms= ReflectionHelper.GetAllReferencedAssemblies();
builder.Services.AddAllDbContexts(opt =>
{
    string connStr = builder.Configuration.GetSection("ConnStr").Value;
    opt.UseSqlServer(connStr);
}, asms);

public record Person
{
    public long Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
    public string Address { get; set; }
}

public class PersonDbContext : DbContext
{
    public DbSet<Person> Persons { get; set; }
    public PersonDbContext(DbContextOptions<PersonDbContext> options) : base(options)
    {
    }
}

internal class PersonDesignTimeDbContextFactory : IDesignTimeDbContextFactory<PersonDbContext>
{
    public PersonDbContext CreateDbContext(string[] args)
    {
        DbContextOptionsBuilder<PersonDbContext> optionsBuilder = new DbContextOptionsBuilder<PersonDbContext>();
        string connStr = Environment.GetEnvironmentVariable("ConnStr");
        optionsBuilder.UseSqlServer(connStr);
        PersonDbContext dbCtx = new PersonDbContext(optionsBuilder.Options);
        return dbCtx;
    }
}


网站公告

今日签到

点亮在社区的每一天
去签到