.Net Core控制台应用程序中DbContext的依赖项注入:在上一个操作完成之前,在此上下文上启动了第二个操作

时间:2019-05-03 18:04:00

标签: c# dependency-injection .net-core entity-framework-core

我已经在.NET Core 2.2上实现了一个项目,该项目由1个控制台应用程序和1个类库组成。控制台应用程序基本上是一个使用者,它订阅一些主题并处理传入的消息。类库是数据库层,我在其中具有存储库。问题是,当与数据库进行交互时,有时会出现错误“ System.InvalidOperationException:在此上下文上启动秒操作,之前的操作完成。不保证任何实例成员都是线程安全的”。

我搜索了类似的问题,但是找不到能解决我问题的解决方案。我曾尝试将DbContext和IRepository都注册为Scoped和Transient,但仍然不断收到错误。我尝试注册DbContext的方式有误吗?

这是我在Consumer.cs中的代码

class Consumer
{
    static readonly IConfigurationRoot _configuration;
    static readonly IServiceProvider _serviceProvider;
    static readonly IRepository _repository;

    static Consumer()
    {
        _configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .Build();

        _serviceProvider = new ServiceCollection()
            .AddSingleton(_configuration)
            .AddTransient<IRepository, Repository>()
            .AddDbContext<QueueContext>(options => options.UseNpgsql(_configuration.GetConnectionString("Queue")), ServiceLifetime.Transient)
            .BuildServiceProvider();

        _repository = _serviceProvider.GetService<IRepository>();
    }

    static void Main(string[] args)
    {
        ...

        RunPoll(here some parameters);
    }

    private static void RunPoll(here some parameters)
    {
        ...

        consumer.OnMessage += async (_, msg) => await ProcessMessageAsync(consumer, msg);

        ...
    }

    private static async Task ProcessMessageAsync(here some parameters)
    {
        ...

        var message = _repository.GetQueueMessage(msg.Value.Id); // On this line I get exception

        if (message == null)
        {
            message = await _repository.AddQueueMessageAsync(msg.Value.Id); // On this line I get exception
        }

        while(message.NumTries < msg.Value.MaxNumAttempts)
        {
            message = await _repository.UpdateQueueMessageTriesAsync(message); // On this line I get exception too
        }

        ...
    }
}

这是我在Respository.cs中的代码

public class Repository : IRepository
{
    private readonly QueueContext _db;

    public Repository(QueueContext db)
    {
        _db = db;
    }

    public QueueMessage GetQueueMessage(long id)
    {
        var message = (from qm in _db.QueueMessages
                       where qm.Id == id
                       select qm).FirstOrDefault();

        return message;
    }

    public async Task<QueueMessage> AddQueueMessageAsync(long id)
    {
        var message = new QueueMessage
        {
            Id = id,
            StartDate = DateTime.Now,
            LastTryDate = DateTime.Now,
            NumTries = 0
        }

        _db.QueueMessages.Add(message);
        await _db.SaveChangesAsync();

        return message;
    }

    public async Task<QueueMessage> UpdateQueueMessageTriesAsync(QueueMessage message)
    {
        if (message != null)
        {
            message.NumTries += 1;
            message.LastTryDate = DateTime.Now;

            _db.QueueMessages.Update(message);
            await _db.SaveChangesAsync();
        }

        return message;
    }
}

这是我在IRepository.cs中的代码

public interface IRepository
{   
    QueueMessage GetQueueMessage(long id);
    Task<QueueMessage> AddQueueMessageAsync(long id);
    Task<QueueMessage> UpdateQueueMessageTriesAsync(QueueMessage message);
}

1 个答案:

答案 0 :(得分:0)

此:

  

_serviceProvider.GetService

不是依赖注入。 DI是在定义采用IRepository的构造函数(或其他方法)时。然后,您可以拥有一个带有非静态方法的Consumer实例,并且在创建Consumer(或调用该方法)时会适当地创建存储库。