WPF.Net 6项目中的DbContextFactory(EF、MVVM)

bihw5rsg  于 2022-11-18  发布在  .NET
关注(0)|答案(1)|浏览(202)

当我使用普通/经典DBContext实现时,我的应用程序运行良好,但当我尝试DbContextFactory时,_contextFactory.CreateDbContext()总是失败并出现“null”异常。我遗漏了什么?
我的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对象示例化的一行?比如this example-IDbContextFactory<MyDbContext> contextFactory对象来自哪里,它在哪里被示例化?谢谢!

q1qsirdb

q1qsirdb1#

我想我已经解决了,虽然我相信你们中的一些人会指出我的错误:)
我刚刚意识到,我已经为数据库迁移创建了自己的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中的代码,并通过我自己的类而不是IDbContextFactory接口初始化了DbContextFactory

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

相关问题