我已经在.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);
}
答案 0 :(得分:0)
此:
_serviceProvider.GetService
不是依赖注入。 DI是在定义采用IRepository
的构造函数(或其他方法)时。然后,您可以拥有一个带有非静态方法的Consumer
实例,并且在创建Consumer
(或调用该方法)时会适当地创建存储库。