在singletonservice中获取transistent / scoped数据库访问

时间:2017-11-30 10:58:43

标签: asp.net asp.net-core

我将我的应用程序从asp核心1.0更新到2.0。在1.0中,我为我的长期导入任务提供了一个解决方案,最初是单身人士。单例使用了DBContext。但在核心2.0中,这个解决方案不起作用。你能救我吗?

我在aps核心1.0中的洗脱液是

services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("LocalConnection")));
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
services.AddTransient<IDataStore, DataStore>();
services.AddSingleton<IImportRepository, ImportRepository>();

public class ImportRepository : IImportRepository
{

    Importer Importer;

    private readonly ApplicationDbContext DBContext;
    private readonly IDataStore store;
    private ImportSet runningSet = null;

    public ImportRepository(ApplicationDbContext context, IDataStore store)
    {
        this.DBContext = context;
        this.store = store;
        Importer = new Importer(DBContext, store);
    }

有了这个问题,我得到错误消息(德语,但我试着翻译)。 “你不能在单身中使用范围服务”

上次尝试使用此解决方案

services.AddSingleton<ImportService>(
                provider => new ImportService((ApplicationDbContext)provider.GetService(typeof(ApplicationDbContext)))
                );

但是在这里我得到了错误消息“无法从根提供程序解析作用域服务'Portal.Data.ApplicationDbContext'。”

如何在Import-Service中访问我的数据库?

3 个答案:

答案 0 :(得分:1)

您可以使用IServiceProvider实例手动解决依赖关系。

public class ImportRepository : IImportRepository
{
    private readonly IServiceProvider _provider;

    public ImportRepository(IServiceProvider provider)
    {
        _provider = provider;
        ...
    }

    public void DoSomething()
    {
        var dBContext = (ApplicationDbContext) provider.GetService(typeof(ApplicationDbContext));
        ...
    }
}

顺便说一下,在GetService<T>();命名空间中定义了一个扩展方法Microsoft.Extensions.DependencyInjection

// using Microsoft.Extensions.DependencyInjection;
var dBContext = provider.GetService<ApplicationDbContext>();

答案 1 :(得分:0)

由于你的单身人士寿命更长并且是共享的,我看到的唯一选择就是你把它当作功能的参数。

public class ImportRepository : IImportRepository
{
    public void DoSomething(ApplicationDbContext context, IDataStore store)
    {
    }
}

另一个选择是使ImportRepository作用域。

答案 2 :(得分:0)

确定。我有一个有效的,但不是完美的。

与Juunas的例子一样,我构建了一个长寿命的游戏

    public async Task RunImportAsync(string fileName, DataService data)
    {
        await Task.Run(() =>
        {
            if (!System.IO.File.Exists(internalPath + fileName))
            {
                throw new Exception($"Datei {fileName} nicht gefunden.");
            }
            [long Operations...]
            data.DBContext.Add(new ImportHistory(set));
            data.DBContext.SaveChanges();
        });
    }

电话很简单

          [HttpPost]
    [Route("runImport")]
    public async Task<IActionResult> RunImport([FromBody]dynamic body)
    {

        string id = ""; 
        try
        {
            id = body.filename;
            _logger.LogInformation($"Import from {id}");
            await ImportService.RunImportAsync(id, DB);
            return StatusCode(StatusCodes.Success_2xx.OK);
        }
        catch (Exception e)
        {
            return SendError(e);
        }


    }

但邮差对此解决方案没有回应。有没有想法,我怎么能解决它?