【问题标题】:Entity Framework Core .Net 6 - Single Context type; Multiple ProvidersEntity Framework Core .Net 6 - 单一上下文类型;多个提供商
【发布时间】:2022-10-18 05:03:43
【问题描述】:

TL;博士:我的问题是,如何正确设置和配置 Entity Framework Core 以使用单个 DbContext 类并管理多个提供程序(SQL Server、Sqlite)的迁移。

在生产中,我有一个托管在 ASP.NET Web API 中的 .NET 6 Blazor WASM 项目。现在,此设置使用 C# 项目(客户端、API、逻辑、数据和共享项目)的标准架构。截至目前,DbContext 被注入到存储库中,然后在逻辑层中使用。一旦请求完成,服务和DbContext 都会被处理掉。一切都很好。

现在,我想创建一个使用相同逻辑和数据层的配套桌面应用程序 (WinUi 3),但需要注意的是使用 SQLite 数据提供程序。现在我可以使用从现有DbContext 继承的新DbContext 类,但这会引入一个问题,即存储库不知道要使用哪个DbContext

我已经尝试按照here (for multiple providers and single context) 声明的文档进行操作,但这似乎并没有为 SQLite 提供程序提供新的ModelSnapshot。因此,生成到update-database 的 SQL 代码仍以 SQL Server 的语法编写。

这是我的项目的架构,下面是我现在的配置:

Data.Migrations.csproj(项目仅用于迁移,如图所示here

// Migrations (folder for SQL Server provider)

// Migrations/Sqlite (folder for SQLite provider)

Data.csproj(带有DbContext 和存储库的项目)

public class Context : DbContext
{
    protected readonly IConfiguration Configuration;

    public Context() { }

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

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // some model configuration
    }

    // DbSets...
}

public interface IRepository<T> where T : class
{
    // some interface methods
}

public class Repository<T> : IRepository<T> where T : class
{
    private DbSet<T> entities;

    public Repository()
    {
    }

    // implement some interface methods
}

public class DbContextFactory : IDesignTimeDbContextFactory<Context>
{
    public Context CreateDbContext(string[] args)
    {
        var optionsBuilder = new DbContextOptionsBuilder<Context>();

        if (DbContextHelper.Provider == "SqlServer")
            optionsBuilder.UseSqlServer(DbContextHelper.ConnectionString,
                    x => x.MigrationsAssembly("Data.Migrations"));
        else if (DbContextHelper.Provider == "Sqlite")
            optionsBuilder.UseSqlite(DbContextHelper.ConnectionString,
                    x => x.MigrationsAssembly("Data.Migrations"));
        else
            throw new InvalidOperationException("Database provider not specified");

        return new Context(optionsBuilder.Options);
    }
}

Logic.csproj:

public interface ICustomerService
{
    // some interface methods
}

public class CustomerService : ICustomerService
{
    protected readonly IRepository<Customer> _customerRepository;

    public CustomerService(IRepository<Customer> customerRepository)
    {
        _customerRepository = customerRepository;
    }

    // implement some interface methods
}

Api.csproj:

// Program class

builder.Services.AddDbContext<Context>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("Context"),
    x => x.MigrationsAssembly("Data.Migrations"))
);

builder.Services.AddTransient<ICustomerService, CustomerService>();

builder.Services.AddScoped(typeof(IRepository<>), typeof(Repository<>));
builder.Services.AddScoped<DbContext, Context>();

WinUi.csproj (WinUi 3 应用 ~= UWP 应用):

// App.xaml.cs

public App()
{
    services.AddDbContext<InSpecContext, Context>(options =>
        options.UseSqlite(DbContextHelper.ConnectionString,
        x => x.MigrationsAssembly("Data.Migrations"))
    );
}

【问题讨论】:

  • @PanagiotisKanavos;不知道你是否注意到了,但我把车队移到了聊天室。见上面的链接
  • Docs 对您有帮助吗?
  • @XinranShen;我想是的,还没有完全完成测试我的场景。文档中没有明确的部分是,您需要为每个提供者(即:Data.SqlServer、Data.Sqlite)一个单独的“迁移”项目。但是在完成这些设置后,我可以在使用单个 Context 类的同时独立管理每个提供程序的迁移

标签: c# sqlite entity-framework asp.net-core entity-framework-core


【解决方案1】:

正如@PanagiotisKanavos 制作的现已删除的 cmets 所建议的那样,我最终摆脱了存储库模式。

然后,我使用位于 Data 项目中的 DbContext 文件为我的每个提供程序创建了一个单独的迁移项目。

然后在Logic 服务中,我不是注入通用存储库或 DbContext,而是按照建议的here 注入IDbContextFactory&lt;MyContext&gt; factory

API 的配置如下所示

builder.Services.AddDbContextFactory<Context>(options =>
    options.UseSqlServer(builder.Configuration.GetConnectionString("Context"),
    x => x.MigrationsAssembly("Data.SqlServer"))
);

WinUi 应用程序的配置如下所示:

services.AddDbContextFactory<Context>(options =>
    options.UseSqlite(DbContextHelper.ConnectionString,
    x => x.MigrationsAssembly("Data.Sqlite"))
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-08-04
    • 1970-01-01
    • 2021-12-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-05
    • 1970-01-01
    相关资源
    最近更新 更多