如何在桌面应用程序中使用 DbContext 和 DI?

Arm*_*our 7 c# wpf entity-framework dependency-injection .net-core

我一直在研究几个非 Web 应用程序,Entity Framework并且一直在努力寻找实现的正确方法Generic Repository使用 DbContext。

我搜索了很多,很多文章都是关于具有短暂上下文的 Web 应用程序。在桌面方法中,我找不到合适的方法。

一种方法是 DbContext per ViewModel但我不同意将 View 与 Repository 层耦合。

另一种是这样使用using子句:

using(var context = new AppDbContext())
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

但是这样我们就不会Unit of Work也不能使用IoC Containers.

那么在桌面应用程序中使用 DbContext 的最佳实践是什么?

Dai*_*Dai 6

ADbContext意味着是短暂的:它本身代表一个工作单元。如果您需要长期的对象状态管理,那么您可以ObjectStateManager直接使用实体框架中的。

为了确保访问 a 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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)