【问题标题】:Discord.NET bot sharing the same DatabaseContext between all modules when using .AddDbContext() and Dependency Injection使用 .AddDbContext() 和依赖注入时,Discord.NET 机器人在所有模块之间共享相同的 DatabaseContext
【发布时间】:2021-06-10 09:31:32
【问题描述】:

我正在创建一个 Discord Bot,它应该在公会成员发出命令时创建和处置 DatabaseContext。问题是模块之间共享相同的DatabaseContext。我已经在使用 .AddDbContext() 而不是 .AddDbContextPool() 所以我不明白这种行为。

我正在使用 Discord.NET、EFCore 和依赖注入。

这是我的 Program.cs 文件:

class Program
{
    private const string _token = "token";
    private readonly DiscordSocketClient _client;
    private readonly CommandService _commands;
    private readonly IServiceProvider _services;

    public static void Main(string[] args)
    => new Program().MainAsync().GetAwaiter().GetResult();

    private Program()
    {
        _client = new DiscordSocketClient();
        _commands = new CommandService();
        _client.Log += Log;
        _commands.Log += Log;
        _services = ConfigureServices();
    }

    private IServiceProvider ConfigureServices()
    {
        var map = new ServiceCollection()
            .AddSingleton(_client)
            .AddSingleton(_commands)
            .AddDbContext<DatabaseContext>(options => 
                options.UseMySql(SharedConfiguration.connectionString,
                new MySqlServerVersion(new Version(5, 7))));

        return map.BuildServiceProvider();
    }

    private Task Log(LogMessage msg)
    {
        Console.WriteLine($"[{DateTime.UtcNow} - {msg.Severity}] {msg.ToString()}");
        return Task.CompletedTask;
    }

    private async Task MainAsync()
    {
        await InitCommands();

        await _client.LoginAsync(TokenType.Bot, _token);
        await _client.StartAsync();

        await Task.Delay(Timeout.Infinite);
    }

    private async Task InitCommands()
    {
        await _commands.AddModulesAsync(Assembly.GetEntryAssembly(), _services);

        _client.MessageReceived += HandleCommandAsync;
    }

    private async Task HandleCommandAsync(SocketMessage messageParam)
    {
        var message = messageParam as SocketUserMessage;
        if (message == null) return;

        int argPos = 0;

        if (!(message.HasStringPrefix("b.", ref argPos) ||
            message.HasMentionPrefix(_client.CurrentUser, ref argPos)) ||
            message.Author.IsBot)
            return;

        var context = new SocketCommandContext(_client, message);

        await _commands.ExecuteAsync(context, argPos, _services);
    }
}

这是一个模块的例子:

public class UserModule : ModuleBase<SocketCommandContext>
{
    private readonly DiscordSocketClient _client;
    private readonly CommandService _commands;
    private readonly DatabaseContext _context;

    private UserModule(DiscordSocketClient client, CommandService commands, DatabaseContext context)
    {
        _client = client;
        _commands = commands;
        _context = context;
    }

    [Command("user")]
    public async Task Stats(IUser dUser = null)
    {
        Console.WriteLine(_context.ContextId);
    }
}

但是,当我运行 b.user 两次时,ContextId 是相同的。 这会在我的应用程序中导致严重的缓存问题,因为该数据库在此不和谐机器人和另一个应用程序之间共享。

我该怎么做才能在每次发出命令时创建DatabaseContext

【问题讨论】:

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


    【解决方案1】:

    这是因为您的机器人是单个实例,因此注入的服务仅解析一次。

    而不是注入DbContext,而是注入IServiceScopeFactory,并为每个请求创建一个单独的范围:

    public class UserModule : ModuleBase<SocketCommandContext>
    {
        private readonly DiscordSocketClient _client;
        private readonly CommandService _commands;
        private readonly IServiceScopeFactory _scopeFactory;
    
        private UserModule(DiscordSocketClient client, CommandService commands, IServiceScopeFactory scopeFactory)
        {
            _client = client;
            _commands = commands;
            _scopeFactory = scopeFactory;
        }
    
        [Command("user")]
        public async Task Stats(IUser dUser = null)
        {
            using(var scope = _scopeFactory.CreateScope())
            {   
                var dbContext = scope.ServiceProvider.GetRequiredService<MyDbContext>();           
                Console.WriteLine(dbContext.ContextId);
            }
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-02-15
      • 2015-10-06
      • 1970-01-01
      • 1970-01-01
      • 2015-10-28
      • 1970-01-01
      • 1970-01-01
      • 2016-08-14
      相关资源
      最近更新 更多