using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.Extensions.Configuration;
using SmartStack.Infrastructure.Persistence;
namespace {{ProjectName}}.Infrastructure.Persistence;
///
/// Factory for creating ExtensionsDbContext at design time (for EF Core CLI tools).
///
/// This enables running migrations from the command line:
///
/// dotnet ef migrations add MyMigration --context ExtensionsDbContext
/// dotnet ef database update --context ExtensionsDbContext
/// dotnet ef migrations list --context ExtensionsDbContext
/// dotnet ef migrations script --context ExtensionsDbContext -o deploy.sql
///
///
/// IMPORTANT: Migrations are stored in the 'extensions' schema, separate from
/// SmartStack Core migrations in the 'core' schema. The Core whitelist entities
/// exposed by SmartStackExtensionDbContext are mapped via
/// ExcludeFromMigrations — they are visible at runtime for FK resolution
/// but NEVER appear in the migrations this factory generates.
///
/// At design time we pass null for ICurrentTenantService — query
/// filters apply only at runtime; the migration generator ignores them.
///
public class DesignTimeExtensionsDbContextFactory : IDesignTimeDbContextFactory
{
public ExtensionsDbContext CreateDbContext(string[] args)
{
// Try to find appsettings.json in various locations
var basePath = Directory.GetCurrentDirectory();
// Look for appsettings.json in common locations
var configPaths = new[]
{
basePath,
Path.Combine(basePath, "..", "{{ProjectName}}.Api"),
Path.Combine(basePath, "..", "..", "src", "{{ProjectName}}.Api"),
};
IConfigurationRoot? configuration = null;
foreach (var path in configPaths)
{
var configPath = Path.Combine(path, "appsettings.json");
if (File.Exists(configPath))
{
configuration = new ConfigurationBuilder()
.SetBasePath(path)
.AddJsonFile("appsettings.json", optional: false)
.AddJsonFile("appsettings.Development.json", optional: true)
.AddJsonFile("appsettings.Local.json", optional: true)
.Build();
break;
}
}
// Fallback: use a default connection string for design-time operations
var connectionString = configuration?.GetConnectionString("DefaultConnection")
?? "Server=(localdb)\\mssqllocaldb;Database={{ProjectName}}_DesignTime;Trusted_Connection=True;MultipleActiveResultSets=true;TrustServerCertificate=True";
var optionsBuilder = new DbContextOptionsBuilder();
optionsBuilder.UseSqlServer(connectionString, b =>
{
b.MigrationsAssembly(typeof(ExtensionsDbContext).Assembly.FullName);
// IMPORTANT: Store migrations history in 'extensions' schema
// This keeps client migrations separate from Core migrations
b.MigrationsHistoryTable("__EFMigrationsHistory", SchemaConstants.Extensions);
});
// tenantService = null at design time — query filters apply at runtime only.
return new ExtensionsDbContext(optionsBuilder.Options, tenantService: null);
}
}