gpt4 book ai didi

c# - 有什么方法可以使 ITicketStore 有范围吗?

转载 作者:行者123 更新时间:2023-12-05 04:55:48 25 4
gpt4 key购买 nike

我正在使用 ITicketStore按照这个article .每当需要执行任何数据库操作时,都会在此创建 DbContext。

在我的代码中,不是通过 using() 语法创建 DbContext,而是通过构造函数注入(inject)。在代码投入生产之前,一切都运行良好。当流量增加时开始出现以下异常。

  • System.InvalidOperationException 在上一个操作完成之前在此上下文中启动了第二个操作。
  • Microsoft.EntityFrameworkCore.DbUpdateConcurrencyException

这可能是因为 ITicketStore 是单例并且使用在多个线程之间共享相同 DbContext 实例的 DI 注入(inject) DbContext。

我更改了代码以通过 using() 创建 DbContext 实例,现在它工作正常。

但我正在尝试通过 DI 注入(inject)来找出使 DbContext 工作的任何方法。

最佳答案

我是这样做的

//in Startup.cs ConfigureServices method  

//I tried using the PostConfigure methods, but it didn't to work for me
services.TryAddEnumerable(ServiceDescriptor.Singleton<IPostConfigureOptions<CookieAuthenticationOptions>, PostConfigureCookieAuthenticationOptionsTicketStore>());
    //This sets the store to the options.
public class PostConfigureCookieAuthenticationOptionsTicketStore : IPostConfigureOptions<CookieAuthenticationOptions>
{
private readonly SingletonTicketStore _store;

public PostConfigureCookieAuthenticationOptionsTicketStore(SingletonTicketStore store) => _store = store;

public void PostConfigure(string name, CookieAuthenticationOptions options) => options.SessionStore = _store;
}

//This implemenation is singleton compatible
public class SingletonTicketStore : ITicketStore
{
private readonly IServiceProvider _services;

public SingletonTicketStore(IServiceProvider services)
{
_services = services;
}

public async Task RemoveAsync(string key) => await WithScopeAsync(s => s.RemoveAsync(key));
public async Task RenewAsync(string key, AuthenticationTicket ticket) => await WithScopeAsync(s => s.RenewAsync(key, ticket));
public async Task<AuthenticationTicket> RetrieveAsync(string key) => await WithScopeAsync(s => s.RetrieveAsync(key));
public async Task<string> StoreAsync(AuthenticationTicket ticket) => await WithScopeAsync(s => s.StoreAsync(ticket));

private async Task WithScopeAsync(Func<ITicketStore, Task> action) => await WithScopeAsync(async t => { await action(t); return true; });
private async Task<T> WithScopeAsync<T>(Func<ITicketStore, Task<T>> action)
{
//This opens a new scope, allowing you to use scoped dependencies
using (var scope = _services.CreateScope())
{
//don't forget to await the result here, of stuff (dbcontext) could be disposed otherwise
return await action(scope.ServiceProvider.GetRequiredService<ITicketStore>());
}
}
}

public class ScopedTicketStore : ITicketStore
{
//your implementation
}

希望这有帮助;)

关于c# - 有什么方法可以使 ITicketStore 有范围吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65184051/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com