![](/img/trans.png)
[英]How to use dotnet-ef tools with DI instanciated DbContext?
[英]How to use DbContext with DI in desktop applications?
我一直在使用Entity Framework
开发几个非 Web 应用程序,并且一直在努力寻找使用 DbContext 实现Generic Repository
的正确方法。
我搜索了很多,很多文章都是关于 web 应用程序的,这些应用程序具有短暂的上下文。 在桌面方法中,我找不到合适的方法。
一种方法是DbContext per ViewModel
但我不同意将 View 与 Repository 层耦合。
另一种是这样使用using
子句:
using(var context = new AppDbContext())
{
// ...
}
但是这样我们就没有Unit of Work
也不能使用IoC Containers
。
那么在桌面应用程序中使用 DbContext 的最佳实践是什么?
DbContext
是短暂的:它本身就代表了一个工作单元。 如果你需要长期的object state管理那么你可以直接使用Entity Framework中的ObjectStateManager
。
为了确保对DbContext
的访问,添加一个接口IDbContextFactory<TDbContext>
(或者如果您只有一个IMyDbContextFactory
类型,则添加一个DbContext
)并将其注入您的 ViewModel 并从中使用一个短暂的DbContext
:
interface IDbContextFactory<TDbContext>
where TDbContext : DbContext
{
TDbContext Create();
}
// Configure:
void ConfigureServices( YourContainer container )
{
container.RegisterSingleton( IDbContextFactory<YourDbContextType1>, // etc );
container.RegisterSingleton( IDbContextFactory<YourDbContextType2>, // etc );
container.RegisterSingleton( IDbContextFactory<YourDbContextType3>, // etc );
}
// Usage:
public class LongLivedViewModel
{
private readonly IDbContextFactory<YourDbContextType3> dbFactory;
public LongLivedViewModel( IDbContextFactory<YourDbContextType3> dbFactory)
{
this.dbFactory = dbFactory ?? throw new ArgumentNullException(nameof(dbFactory));
this.DoSomethingCommand = new RelayCommand( this.DoSomethingAsync )
}
public RelayCommand DoSomethingCommand { get; }
public async RelayCommand DoSomethingAsync()
{
using( YourDbContextType3 db = this.dbFactory.Create() )
{
// do stuff
await db.SaveChangesAsync();
}
}
}
Entity Framework Core 有一个内置的 IDbContextFactory 接口。
例如,如果使用 SQL 服务器,则在 ConfigureServices 方法中声明以下内容(在 WPF 通常放在 App.xaml.cs 中)。
private static void ConfigureServices(IServiceCollection services)
{
services.AddDbContextFactory<MyDbContext>(
options =>
options.UseSqlServer(MyConnectionString));
}
确保 MyDbContext 公开此构造函数:
public class MyDbContext : DbContext
{
public MyDbContext(DbContextOptions<MyDbContext> options)
: base(options)
{
}
}
之后在将使用上下文的 class 中使用构造函数注入(可以在 ViewModel 层或 Model 层中,具体取决于您的架构):
private readonly IDbContextFactory<MyDbContext> _contextFactory;
public ModelClass(IDbContextFactory<MyDbContext> contextFactory)
{
this._contextFactory = contextFactory;
}
public void DatabaseOperationMethod()
{
using (var context = this._contextFactory.CreateDbContext())
{
// Do database stuff
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.