【发布时间】: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