繁体   English   中英

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

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM