[我一直在使用Entity Framework
处理多个非Web应用程序,但一直很难为我找到一种使用DbContext实现Generic Repository
的正确方法。
我已经搜索了很多,很多文章都是关于具有短暂生存期的Web应用程序的。在桌面方法中,我找不到合适的方法。
一种方法是DbContext per ViewModel
,但我不同意将View与Repository层耦合。
[另一个正在以这种方式使用using
子句:
using(var context = new AppDbContext())
{
// ...
}
但是这样,我们将没有Unit of Work
,也不能使用IoC Containers
。
那么在桌面应用程序中使用DbContext的解决方案是什么?
A DbContext
被认为是短暂的:它本身代表一个工作单元。如果需要长期的对象状态管理,则可以直接在Entity Framework中使用ObjectStateManager
。
为了确保对DbContext
的访问,请添加接口IDbContextFactory<TDbContext>
(如果只有一个IMyDbContextFactory
类型,则只需添加DbContext
),然后将其注入到ViewModels中,并使用一个短暂的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();
}
}
}