把原来的MalemaDbContext改成下面的这个样子。我们希望这个数据库连接字符串,还有Provider都是由DI来控制的。
using Microsoft.EntityFrameworkCore;
namespace Data
{
public class MalemaDbContext : DbContext
{
public MalemaDbContext(DbContextOptions<MalemaDbContext> options)
: base(options)
{
this.Database.EnsureCreated();
}
public DbSet<Student> Students { get; set; }
}
}
创建一个使用DbContext的类 StudentService
using Data;
using Microsoft.EntityFrameworkCore;
namespace ConsoleApp
{
public class StudentService
{
private readonly MalemaDbContext dbContext;
private readonly IDbContextFactory<MalemaDbContext> dbContextFactory;
public StudentService(MalemaDbContext dbContext, IDbContextFactory<MalemaDbContext> dbContextFactory)
{
this.dbContext = dbContext;
this.dbContextFactory = dbContextFactory;
}
public void Add(Student student)
{
dbContext.Add(student);
dbContext.SaveChanges();
}
public void Add2(Student student)
{
//可以看到我们这边用的是 dbContextFactory创建出来的。 这样的功能是很用的。
//在一些后台任务当中,我们希望每一次的任务,都是一个全新DbContext。
//我们的这个StudentService就可以被注册成单例
using (var dbContext = dbContextFactory.CreateDbContext())
{
dbContext.Add(student);
dbContext.SaveChanges();
}
}
}
}
using Data;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var sp = GetSserviceProvider();
var studentService = sp.GetService<StudentService>();
studentService.Add(new Student() { Name = "abc" });
studentService.Add2(new Student() { Name = "abc2" });
}
private static ServiceProvider GetSserviceProvider()
{
var connectionString = "Data Source=127.0.0.1;Initial Catalog=MalemaEFCoreExample;Persist Security Info=True;User Id=sa;Password=malema987%^&";
var optionBuilder = new DbContextOptionsBuilder<MalemaDbContext>();
optionBuilder.UseSqlServer(connectionString);
var services = new ServiceCollection();
// services.AddDbContext<MalemaDbContext>(options => options.UseSqlServer(connectionString)); //注入DbContext
// services.AddDbContextFactory<MalemaDbContext>(options => options.UseSqlServer(connectionString)); // 注入 DbContext factory
services.AddDbContextPool<MalemaDbContext>(options => options.UseSqlServer(connectionString), poolSize: 64); //注入 DbContext 池
// 注入 DbContext factory 来从池中生成 Dbcontext
services.AddPooledDbContextFactory<MalemaDbContext>(options => options.UseSqlServer(connectionString), poolSize: 64);
services.AddScoped<StudentService, StudentService>();
var sp = services.BuildServiceProvider();
return sp;
}
}
}
使用 DbContext池,在性能上可以获得一些提升。
services.AddDbContextFactory 和 services.AddPooledDbContextFactory
完整的代码在 https://gitee.com/malema/Examples/tree/dbcontext/di/EFCore-Example 可以用下面的git命令把代码签出到本地
git clone https://gitee.com/malema/Examples
git checkout dbcontext/di
在使用池的时候有一个要注意的事项。SqlConnection默认池大小是 100,小于 DbContext池的默认值128. 所以在注入的时候我们需要配置一个更小的值。或者我们得去更改我们的数据库连接字符串
在上面的字符串里面加上;Max Pool Size=1024;Pooling=true;
Pooling是默认开启的可以不管它。
使用DbContextOptionsBuilder
var builder = new DbContextOptionsBuilder<MalemaDbContext>();
builder.UseSqlServer(connectionString);
var dbcontext = new MalemaDbContext(builder.Options);
单元测试这边也是这样实现的