Vorrei iniettare il mio .NET Core EntityFramework DbContext
(seduto in una libreria standard .net) nella mia app WPF.
Ho provato questo approccio Unity :
All'avvio
var container = new UnityContainer();
container.RegisterType<ApplicationDbContext>();
var mainWindow = container.Resolve<MainWindow>();
base.OnStartup(e);
Finestra principale
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());
}
Ma ottengo questo errore in container.Resolve<MainWindow>()
:
Il tipo corrente, System.Collections.Generic.IReadOnlyDictionary`2 [System.Type, Microsoft.EntityFrameworkCore.Infrastructure.IDbContextOptionsExtension], è un'interfaccia e non può essere costruita. Ti manca una mappatura dei tipi?
Qualcuno sa se sto facendo qualcosa di sbagliato? Qualsiasi suggerimento su un modo migliore per farlo è benvenuto
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));
}
Come suggerito da Nkosi, ho rimosso ApplicationDbContext(options)
ctor dal contesto e ho eliminato l'errore. Comunque ora sto controllando il valore di Db
qui in MainWindow
:
private ICommand goPack;
public ICommand GoPack
{
get
{
return goPack
?? (goPack = new ActionCommand(() =>
{
var c = _db.Parts;
FrameContent.Navigate(new PageConsignments());
}));
}
}
Ma restituisce null
L'errore originale era perché il contenitore stava selezionando il costruttore che prevedeva DbContextOptionsBuilder
che il conateinr non sapeva come risolvere correttamente.
Poiché il contesto è in fase di configurazione all'interno del OnConfiguring
non è necessario
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{ }
Rimuovi quel costruttore in modo che il contenitore risolva il contesto senza errori.
A seconda del flusso di inizializzazione delle dipendenze e dell'accesso ad esso, tale contesto dovrebbe essere effettivamente iniettato esplicitamente in un modello di vista e non direttamente nella vista.
Seguendo MVVM, hanno tutte le dipendenze e le proprietà associabili necessarie nel modello di vista
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());
}));
}
}
}
Aggiorna la vista per dipendere dal modello di vista
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());
}
}
Tutto ciò che rimane ora è assicurarsi che tutte le dipendenze siano registrate con il contenitore
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();
}
}
Ove mai possibile, il principio delle dipendenze esplicite tramite iniezione del costruttore dovrebbe essere preferito all'iniezione di proprietà.
Ma poiché la maggior parte delle visualizzazioni non si presta bene all'iniezione del costruttore, di solito viene applicata quest'ultima. Assicurandosi che il modello di vista abbia tutte le dipendenze necessarie prima di iniettarlo nella vista, si assicura che tutti i valori richiesti siano disponibili quando necessario.