Мое приложение работает нормально, когда я использую простую/классическую реализацию DBContext, но когда я пытаюсь DbContextFactory, _contextFactory.CreateDbContext() всегда терпит неудачу с «нулевым» исключением. Что мне не хватает?
Мой App.xaml.cs (при использовании DBContext никаких изменений в этом файле не требовалось):
private void ConfigureServices(IServiceCollection services)
{
string defaultConnection = Settings.Default.DefaultConnection;
services.AddDbContextFactory<MyDbContext>(options => options.UseMySql(defaultConnection, ServerVersion.AutoDetect(defaultConnection)));
services.AddTransient(typeof(MainWindow));
}
MyDbContext.cs файл (никаких изменений не потребовалось, так как он уже соответствует требованиям DbContextFactory конструктора):
public class MyDbContext : DbContext
{
public MyDbContext (DbContextOptions<MyDbContext> options)
: base(options)
{
}
// DbSets
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
string defaultConnection = Settings.Default.DefaultConnection;
var options = new DbContextOptionsBuilder<MyDbContext>()
.UseMySql(defaultConnection, ServerVersion.AutoDetect(defaultConnection))
.Options;
}
optionsBuilder.UseLazyLoadingProxies();
// To be disabled in production
optionsBuilder.LogTo(Console.WriteLine, LogLevel.Information);
optionsBuilder.EnableSensitiveDataLogging();
optionsBuilder.EnableDetailedErrors();
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// Table building logic for EF code-first
}
}
MainWindow.xaml.cs файл:
public partial class MainWindow : Window
{
private readonly IDbContextFactory<MyDbContext> _contextFactory;
private SomeVieModel _someVieModel;
public MainWindow()
{
InitializeComponent();
var _context = _contextFactory.CreateDbContext(); // Throws 'null' exception
// Probably should be instantiating a new DbContext
// in the VM itself, instead of passing it on?
_someVieModel = new SomeVieModel(_context);
}
}
Я проверил множество примеров Blazor из-за отсутствия примеров WPF, и я чувствую, что упускаю что-то очень простое, какую-то одну строку DbContextFactory экземпляра объекта? Как в этом примере - откуда берется IDbContextFactory<MyDbContext> contextFactory объект и где он создается? Спасибо!
Спасибо, Юрген! То, что вы говорите, имеет смысл, и я частично обдумывал это, но как-то в моей голове это выглядело как плохая идея изменить таким образом само главное окно. Конечно, это как любое другое окно, и я просто должен был это сделать :)





Я думаю, что у меня это получилось, хотя я уверен, что некоторые из вас укажут на ошибку моего пути :)
Я только что понял, что у меня уже есть собственный класс DbContextFactory, созданный для миграции базы данных, потому что иначе EF Core не смог бы подключиться к базе данных только через класс DbContext проекта.
public class MyDbContextFactory : IDesignTimeDbContextFactory<MyDbContext>
{
public MyDbContext CreateDbContext(string[]? args = null)
{
string defaultConnection = Settings.Default.DefaultConnection;
var optionsBuilder = new DbContextOptionsBuilder<MyDbContext>();
optionsBuilder.UseMySql(defaultConnection, ServerVersion.AutoDetect(defaultConnection));
return new MyDbContext(optionsBuilder.Options);
}
}
Я прокомментировал код в App.xaml.cs out и инициализировал DbContextFactory через свой собственный класс вместо IDbContextFactory интерфейса:
public partial class MainWindow : Window
{
private readonly MyDbContextFactory _contextFactory;
private SomeVieModel _someVieModel;
public MainWindow()
{
InitializeComponent();
_contextFactory = new MyDbContextFactory();
_someVieModel = new SomeVieModel(_contextFactory);
}
}
И вызвал CreateDbContext() в модели представления:
public class SomeVieModel : ViewModelBase
{
private readonly MyDbContextFactory _contextFactory;
public SomeVieModel(MyDbContextFactory contextFactory)
{
_contextFactory = contextFactory;
await LoadDBStuff();
}
private async Task LoadDBStuff()
{
using (var context = _contextFactory.CreateDbContext())
{
await context.SomeDataModel.LoadAsync();
SomeDataModelObservableCollection = context.SomeDataModel.Local.ToObservableCollection();
}
}
}
Ошибка заключалась в том, что вы не внедрили
IDbContextFactory<MyDbContext>в конструкторMainWindow. Вот почему фабрика так и не была создана, а вы получилиNullReferenceException. Все остальное выглядит нормально - может быть, за исключением того, что что-то вводится в окно, которое затем просто передает его в модель представления вместо того, чтобы вводить вещи туда, где они нужны. Но это касается дизайна, а не ошибки, которую вы получили.