如何将 .net core EF 注入 WPF 应用程序

Bas*_*sie 2 c# wpf entity-framework-core .net-standard

我想将我的 .NET Core EntityFramework DbContext(位于 .net 标准库中)注入我的 WPF 应用程序。

我尝试了这种 Unity 方法

启动时

var container = new UnityContainer();
container.RegisterType<ApplicationDbContext>();
var mainWindow = container.Resolve<MainWindow>();

base.OnStartup(e);
Run Code Online (Sandbox Code Playgroud)

主窗口

private ApplicationDbContext _db;
[Dependency]
public ApplicationDbContext Db
{
    get
    {
        return _db;
    }
    set
    {
        _db = value;
    }
}

public MainWindow()
{
    //StandardDatabase.Commands.Test();

    InitializeComponent();
    DataContext = this;
    FrameContent.Navigate(new PageConsignments());
}
Run Code Online (Sandbox Code Playgroud)

但是我在container.Resolve<MainWindow>()以下位置收到此错误:

当前类型 System.Collections.Generic.IReadOnlyDictionary`2[System.Type,Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptionsExtension] 是一个接口,无法构造。您是否缺少类型映射?

有谁知道我是否做错了什么?欢迎任何关于更好的方法的建议

应用程序数据库上下文

public ApplicationDbContext() : base() { }

public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
    : base(options)
{ }

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder
        .UseLazyLoadingProxies()
        .UseSqlServer("Server=L-TO-THE-APTOP\\SQLEXPRESS;Database=Maloli;Trusted_Connection=True;MultipleActiveResultSets=true");

    optionsBuilder.ConfigureWarnings(x => x.Ignore(CoreEventId.LazyLoadOnDisposedContextWarning));
}
Run Code Online (Sandbox Code Playgroud)

根据 Nkosi 的建议,我ApplicationDbContext(options)从上下文中删除了ctor,从而消除了错误。但是我现在正在检查Db此处的值MainWindow

private ICommand goPack;
public ICommand GoPack
{
    get
    {
        return goPack
            ?? (goPack = new ActionCommand(() =>
            {
                var c = _db.Parts;
                FrameContent.Navigate(new PageConsignments());
            }));
    }
}
Run Code Online (Sandbox Code Playgroud)

但它返回 null

Nko*_*osi 5

最初的错误是因为容器正在选择预期的构造函数,DbContextOptionsBuilder而 conateinr 不知道如何正确解析。

由于上下文是在OnConfiguring覆盖中配置的,因此不需要

public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
    : base(options)
{ }
Run Code Online (Sandbox Code Playgroud)

删除该构造函数,以便容器解析上下文而不会出错。

根据依赖初始化的流程和对它的访问,该上下文应该真正显式地注入到视图模型中,而不是直接注入到视图中。

遵循 MVVM,在视图模型中拥有所有必要的依赖项和可绑定属性

public class MainWindowViewModel : BaseViewModel {
    private readonly ApplicationDbContext db;

    public MainWindowViewModel(ApplicationDbContext db) {
        this.db = db;            
    }

    private ICommand goPack;
    public ICommand GoPack {
        get {
            return goPack
                ?? (goPack = new ActionCommand(() =>
                {
                    var c = db.Parts;
                    FrameContent.Navigate(new PageConsignments());
                }));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

更新视图以依赖于视图模型

public class MainWindow : Window {
    [Dependency]
    public MainWindowViewModel ViewModel {
        set { DataContext = value; }
    }

    public MainWindow() {
        InitializeComponent();
        Loaded += OnLoaded;
    }

    void OnLoaded(object sender, EventArgs args) {
        FrameContent.Navigate(new PageConsignments());
    }
}
Run Code Online (Sandbox Code Playgroud)

现在剩下的就是确保所有依赖项都注册到容器中

public class App : Application {
    protected override void OnStartup(StartupEventArgs e) {
        IUnityContainer container = new UnityContainer();
        container.RegisterType<ApplicationDbContext>();
        container.RegisterType<MainWindowViewModel>();
        container.RegisterType<MainWindow>();

        MainWindow mainWindow = container.Resolve<MainWindow>();
        mainWindow.Show();
    }
}
Run Code Online (Sandbox Code Playgroud)

在可能的情况下,通过构造函数注入的显式依赖原则应该优先于属性注入。

但是由于大多数视图不能很好地用于构造函数注入,因此通常应用后者。通过在将视图模型注入视图之前确保视图模型具有所有必要的依赖项,您可以确保在需要时所有必需的值都可用。