[英]How to inject .net core EF into WPF application
I would like to inject my .NET Core EntityFramework DbContext
(sitting in a .net standard library) into my WPF app. 我想将.NET Core EntityFramework
DbContext
(位于.net标准库中)注入WPF应用程序。
I tried this Unity approach : 我尝试了这种Unity方法 :
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());
}
But I get this error at container.Resolve<MainWindow>()
: 但是我在
container.Resolve<MainWindow>()
处收到此错误:
The current type, System.Collections.Generic.IReadOnlyDictionary`2[System.Type,Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptionsExtension], is an interface and cannot be constructed.
当前类型System.Collections.Generic.IReadOnlyDictionary`2 [System.Type,Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptionsExtension]是一个接口,无法构造。 Are you missing a type mapping?
您是否缺少类型映射?
Does anyone know if I'm doing something wrong? 有人知道我做错了吗? Any suggestions on a better way of doing this are welcome
欢迎提出任何更好的方法建议
ApplicationDbContext 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));
}
As per Nkosi's suggestion, I removed the ApplicationDbContext(options)
ctor from the context, and that got rid of the error.However I am now checking the value of Db
here in MainWindow
: 根据Nkosi的建议,我从上下文中删除了
ApplicationDbContext(options)
ctor,并且摆脱了错误。但是,我现在在MainWindow
检查Db
的值:
private ICommand goPack;
public ICommand GoPack
{
get
{
return goPack
?? (goPack = new ActionCommand(() =>
{
var c = _db.Parts;
FrameContent.Navigate(new PageConsignments());
}));
}
}
But it returns null
但它返回
null
The original error was because the container was selecting the constructor that expected DbContextOptionsBuilder
which the conateinr did not know how to resolve properly. 最初的错误是因为容器选择了预期
DbContextOptionsBuilder
的构造函数,而conateinr不知道该如何正确解决。
Since the context is being configured within the OnConfiguring
override then there is no need for 由于上下文是在
OnConfiguring
覆盖范围内配置的,因此不需要
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{ }
Remove that constructor so the container resolve the context without errors. 删除该构造函数,以便容器解析上下文而不会出现错误。
Depending on the flow of dependency initialization and access to it, that context should really be explicitly injected into a view model and not directly on the View. 根据依赖关系初始化和访问的流程,该上下文确实应该显式注入视图模型中,而不是直接在视图上。
Following MVVM, have all the necessary dependencies and bindable properties in the view model 跟随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());
}));
}
}
}
Update the View to depend on the view model 更新视图以取决于视图模型
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());
}
}
All that is left now is to make sure all dependencies are registered with container 现在剩下的就是确保所有依赖项都已在容器中注册
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();
}
}
Where ever possible, The Explicit Dependencies Principle via constructor injection should be preferred over property injection. 在任何可能的情况下,通过构造函数注入的显式依赖关系原则应优先于属性注入。
But since most views do not lend well to constructor injection the latter is usually applied. 但是由于大多数视图都不适用于构造函数注入,因此通常会应用后者。 By making sure the view model has all the necessary dependencies before injecting it into the view you ensure that all required values are available when needed.
通过在将视图模型注入视图之前确保视图模型具有所有必要的依赖关系,可以确保在需要时所有必需的值都可用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.