C# 如果父对象是单例对象,那么创建dbcontext(EF-core)的最佳实践是什么?
我用。我将使用实体框架核心来保存状态。我遇到了一个问题。IStorage接口以单例的形式注入,因为使用此接口的其他对象以单例的形式注入C# 如果父对象是单例对象,那么创建dbcontext(EF-core)的最佳实践是什么?,c#,dependency-injection,entity-framework-core,botframework,dbcontext,C#,Dependency Injection,Entity Framework Core,Botframework,Dbcontext,我用。我将使用实体框架核心来保存状态。我遇到了一个问题。IStorage接口以单例的形式注入,因为使用此接口的其他对象以单例的形式注入 services.AddSingleton<IStorage>(new MyDbStorage()); //<-- my storage with dbcontext services.AddSingleton<UserState>(); //This class has ctor
services.AddSingleton<IStorage>(new MyDbStorage()); //<-- my storage with dbcontext
services.AddSingleton<UserState>(); //This class has ctor with IStorage param
services.AddSingleton<ConversationState>(); //And this class has ctor with IStorage param
services.AddSingleton(sp =>
{
var userState = sp.GetService<UserState>();
var conversationState = sp.GetService<ConversationState>();
return new BotStateSet(userState, conversationState);
});
有关详细信息,请参见。
我知道。
您能为我推荐一些创建dbcontext的选项吗?
我考虑过DbContextFactory,但我不知道如何确切地创建它
更新
我已经更新了代码。请参阅第一行。首先,请不要使用接口抽象MyDbContext,否则您将无法访问EF fetures或将尝试隐藏EntityFramework命名空间。使用扩展名。这样,DbContext将被注册为作用域,它的最佳生存期是什么 将IServiceProvider注入到singleton UserState和ConversationState中,然后仅在需要时创建作用域并解析此作用域内的MyDbContext实例 但是,如果UserState和ConversationState所做的工作应该作为单个事务执行,这意味着在同一个DbContext实例上,那么最好在BotStateSet中解析MyDbContext,并将其作为参数传递到UserState和ConversationState的方法中
我不熟悉Virtual Assistant,但如果可以对状态类(至少对UserState和ConversationState)使用瞬态生存期,它将允许您将MyDbContext注入构造函数,避免将其作为参数传递。那么,为什么您不能简单地添加is as.AddTransient?其他人可能是单身,但这一个是暂时的。还是我遗漏了什么?@Fabjan,UserState是个单身汉。这意味着ctor将只执行一次。正如您所知,UserState-ctor具有param-IStorage。UserState对象将不会在下一个请求或其他任何请求中重新创建。这意味着历史就像一个瞬间,这并不重要。在本例中,瞬态与单例相同。好的,当再次读取代码时,他们使用的是CosmosDbStorage,而不是DbContext,所以没关系。但是整个代码看起来很难看,我问自己为什么?几乎在每一行代码上。不幸的是,我不能编辑这个集合。它位于Microsoft.Bot.Builder命名空间内。
public class UserState
{
private readonly IServiceProvider _provider;
public UserState(IServiceProvider provider)
{
_provider = provider;
}
public async Task DoWorkAsync()
{
using (var scope = _provider.CreateScope())
using (var ctx = scope.ServiceProvider.GetService<MyDbContext>())
{
// do work
await ctx.SaveChangesAsync();
}
}
}