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

时间:2018-11-24 15:07:04

标签: c# wpf entity-framework-core .net-standard

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

我尝试了this Unity approach

OnStartup

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

base.OnStartup(e);

MainWindow

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());
}

但是我在container.Resolve<MainWindow>()遇到此错误:

  

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

有人知道我做错了吗?欢迎提供任何更好的方法建议

ApplicationDbContext

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));
}

根据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());
            }));
    }
}

但是它返回null

1 个答案:

答案 0 :(得分:4)

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

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

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

删除该构造函数,以便容器无错误地解析上下文。

取决于依赖关系初始化和对其进行访问的流程,该上下文确实应该显式地注入视图模型中,而不是直接在视图上。

继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());
                }));
        }
    }
}

更新视图以取决于视图模型

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());
    }
}

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

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();
    }
}

在可能的情况下,应优先使用通过构造函数注入的The Explicit Dependencies Principle而不是属性注入。

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