在实际代码中有时候我们会希望每一次运行都需要一个新的对象, 比如EFCore当中的 DbContext。 因为DbContext有一些设计当中存在的问题。
(该对象也不适合配置成Transient)
private static void Register(IServiceCollection services, IConfiguration configuration)
{
services.AddSingleton<IMessageWriter, MessageWriter>();
services.AddSingleton<Worker>();
//在这边注入 Func<MalemaDbContext>
services.AddSingleton(sp =>
{
var conn = configuration.GetConnectionString("malema");
return new Func<MalemaDbContext>(() =>
{
var builder = new DbContextOptionsBuilder<MalemaDbContext>();
builder.UseSqlServer(conn);
return new MalemaDbContext(builder.Options);
});
});
}
使用它
using Microsoft.Extensions.Logging;
using System;
using System.Threading.Tasks;
namespace Malema.net.Example
{
public class Worker
{
private readonly IMessageWriter _messageWriter;
private readonly Func<MalemaDbContext> _func;
public Worker(IMessageWriter messageWriter, Func<MalemaDbContext> func)
{
_messageWriter = messageWriter;
_func = func;
}
public async Task ExecuteAsync()
{
_messageWriter.Write($"Worker running at: {DateTimeOffset.Now}");
for(int i=0;i<10;i++)
{
//某些情况下我们希望dbContext每次都是不一样的
using (var dbContext = _func())
{
//
}
}
}
}
}
通过使用 CreateScope() 我们也做到类似上面的效果. 详看 scope
Func<>这种方式可能不太好理解,更好理解的方式我们可以创建一个IMalemaDbContextFactory,这样它的注入方式就可以跟其它类一模一样了。
备注:实际上 EF5.0 之后有支持
IDbContextFactory<MalemaDbContext>
示例代码如下
var services = new ServiceCollection();
services.AddDbContextFactory<MalemaDbContext>(x => x.UseInMemoryDatabase("malema"));
//serviceCollection.AddPooledDbContextFactory<MalemaDbContext>(x => x.UseInMemoryDatabase("mlema"));//pool的方式
var factory = services.BuildServiceProvider().GetRequiredService<IDbContextFactory<MalemaDbContext>>();
using (var context = factory.CreateDbContext())
{
}