创建一个 .NET 类库项目,项目名字为 BooksEFCore
引用以下 Nuget 包
Microsoft.EntityFrameworkCore.Relational
Microsoft.EntityFrameworkCore.SqlServer
Microsoft.EntityFrameworkCore.Tools
创建实体类 Book
// 把Book类声明为一个记录类,而不是普通的类,主要是为了让编译器自动生成ToString方法,简化对象的输出
public record Book
{
public Guid Id { get; set; }
public string Name { get; set; }
public double Price { get; set; }
}
配置实体类
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Builders;
class BookConfig : IEntityTypeConfiguration<Book>
{
public void Configure(EntityTypeBuilder<Book> builder)
{
builder.ToTable("T_Books2");
}
}
创建上下文类【注意,这里有跟单体 EF Core 项目不一样的地方,看注释】
using Microsoft.EntityFrameworkCore;
public class MyDbContext:DbContext
{
public DbSet<Book> Books { get; set; }
//注意:
//在运行时通过读取配置来确定要连接的数据库
//不再重写 OnConfiguring 方法和在其中调用 UseSqlServer 等方法来设置要使用的数据库
//为 MyDbContext 类增加了 DbContextOptions<MyDbContext> 类型参数的构造方法
//DbContextOptions 是一个数据库连接配置对象,在 ASP.NET Core 项目中提供对 DbContextOptions 的配置
public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
{
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.ApplyConfigurationsFromAssembly(this.GetType().Assembly);
}
}
创建一个 Asp.net core webapi 项目,命名为 “EFCore测试用WebAPI项目1”
引用 EF Core 类项目 BooksEFCore
打开 appsettings.json 文件并添加数据库连接字符串配置
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"ConnectionStrings": {
"Default": "Server=(localdb)\\mssqllocaldb;Database=TestDB;Trusted_Connection=True;MultipleActiveResultSets=true"
}
}
打开 Program.cs 文件,注册数据库上下文服务
using Microsoft.EntityFrameworkCore;
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
// 注册数据库上下文服务
// 使用AddDbContext方法来通过依赖注入的方式让MyDbContext采用指定的连接字符串连接数据库。
// 由于AddDbContext方法是泛型的,因此可以为同一个项目中的多个不同的上下文设定连接不同的数据库。
builder.Services.AddDbContext<MyDbContext>(opt =>
{
string connStr = builder.Configuration.GetConnectionString("Default")!;
opt.UseSqlServer(connStr);
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}
app.UseHttpsRedirection();
app.UseAuthorization();
app.MapControllers();
app.Run();
创建 TestController 控制器,编写数据库读写的测试代码
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("[controller]/[action]")]
public class TestController : ControllerBase
{
private readonly MyDbContext dbCtx;
/// <summary>
/// 用依赖注入的形式来创建上下文
/// </summary>
/// <param name="dbCtx"></param>
public TestController(MyDbContext dbCtx)
{
this.dbCtx = dbCtx;
}
[HttpPost]
public async Task<long> Save()
{
dbCtx.Add(new Book { Id = Guid.NewGuid(), Name = "零基础趣学C语言", Price = 59 });
await dbCtx.SaveChangesAsync();
return dbCtx.Books.LongCount();
}
}
生成实体类的迁移脚本
回到 EF Core 类项目 BooksEFCore
新建一个实现 IDesignTimeDbContextFactory 接口的类 MyDesignTimeDbContextFactory
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
//在多项目的环境下执行 EF Core 的数据库迁移有很多特殊的要求
//容易出错,因为数据库连接在其它项目中
//可以通过 IDesignTimeDbContextFactory 接口来解决这个问题
//当项目中存在一个 IDesignTimeDbContextFactory 接口的实现类的时候,
//数据库迁移工具就会调用这个实现类的 CreateDbContext 方法来获取上下文对象,
//然后迁移工具会使用这个上下文对象来连接数据库
//此代码只用于开发环境
//生产环境可以去掉此代码
class MyDesignTimeDbContextFactory : IDesignTimeDbContextFactory<MyDbContext>
{
public MyDbContext CreateDbContext(string[] args)
{
DbContextOptionsBuilder<MyDbContext> builder = new();
string connStr = "Server=(localdb)\\mssqllocaldb;Database=TestDB;Trusted_Connection=True;MultipleActiveResultSets=true";
//也可以从环境变量或者其它配置文件中读取,如下:
//string connStr = Environment.GetEnvironmentVariable("ConnectionStrings:BooksEFCore");
builder.UseSqlServer(connStr);
return new MyDbContext(builder.Options);
}
}
设置 BooksEFCore 为启动项目
打开 菜单-工具-Nuget包管理-程序包管理器控制台,并选中 BooksEFCore
执行 Add-Migration Init
命令生成数据库迁移脚本
然后执行 Update-database
命令即可完成数据库的创建