Hello fellows !
I have researched the Imigrator. and Migration commands !
https://github.com/aspnet/EntityFrameworkCore/blob/04607ac00983705b3b1d4d4ca9834364edd36a01/src/EFCore.Relational/Migrations/IMigrator.cs
And my main target is to store Migration not in Cs files!
I want to store migrations files in database or in some xml files!
And apply migrations with out relaunching the main app!
As I said before is need for enterprise scenarios, when application must work in 24/7 servicemodel!
It'is very sad that dotnet/coreclr still could not provide unloading of assembly!
https://github.com/dotnet/coreclr/pull/18476
I have a few conceptual and technicals questions !
1.Its possible to Realize IMigrationsAssembly that will store migrations in database or xml files, not in cs files ?
https://github.com/aspnet/EntityFrameworkCore/blob/04607ac00983705b3b1d4d4ca9834364edd36a01/src/EFCore.Relational/Migrations/IMigrationsAssembly.cs
The migration architecture is hard binded to work with assembly!
I think is not right that with architecure principes, that the migrations are stored in Cs files.
I understand, that it is very nice that U inspired with Django and Ruby_on_Rails frameworks, with there simplicity to work with migrations!
Maybe U shall overview the architecture of migrations ?
Maybe must be some kind of MigrationProvider, that will store all migrations ?
By option it could be cs files,xml files,json files,or database storage ?
protected virtual void PopulateMigrations(
IEnumerable<string> appliedMigrationEntries,
string targetMigration,
out IReadOnlyList<Migration> migrationsToApply,
out IReadOnlyList<Migration> migrationsToRevert)
{
// ΠΡΠΈΠΌΠ΅Π½Π΅Π½Π½ΡΠ΅ ΠΌΠΈΠ³ΡΠ°ΡΠΈΠΈ
var appliedMigrations = new Dictionary<string, TypeInfo>();
// ΠΠ΅ ΠΡΠΈΠΌΠ΅Π½Π΅Π½Π½ΡΠ΅ ΠΌΠΈΠ³ΡΠ°ΡΠΈΠΈ
var unappliedMigrations = new Dictionary<string, TypeInfo>();
var appliedMigrationEntrySet = new HashSet<string>(appliedMigrationEntries, StringComparer.OrdinalIgnoreCase);
//ΠΡΠ»ΠΈ Π½Π΅ΡΡ ΠΌΠΈΠ³ΡΠ°ΡΠΈΠΉ Π² _migrationsAssembly ΡΠΎ ΠΏΠΈΡΠ΅ΠΌ ΡΡΠΎ ΠΌΠΈΠ³ΡΠ°ΡΠΈΠΈ Π½Π΅ Π½Π°ΠΉΠ΄Π΅Π½Ρ
if (_migrationsAssembly.Migrations.Count == 0)
{
_logger.MigrationsNotFound(this, _migrationsAssembly);
}
/// ΠΠ΅ΡΠ΅Π±ΠΈΡΠ°Π΅ΠΌ Π²ΡΠ΅ ΠΌΠΈΠ³ΡΠ°ΡΠΈΠΈ Π² _migrationsAssembly
foreach (var migration in _migrationsAssembly.Migrations)
{
// ΠΡΠ»ΠΈ appliedMigrationEntrySet ΡΠΎΠ΄Π΅ΡΠΆΠΈΡ ΠΌΠΈΠ³ΡΠ°ΡΠΈΡ _migrationsAssembly
// ΡΠΎ Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ ΠΊ ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½ΡΠΌ
if (appliedMigrationEntrySet.Contains(migration.Key))
{
appliedMigrations.Add(migration.Key, migration.Value);
}
else
{ //ΠΡΠ»ΠΈ Π½Π΅Ρ ΡΠΎ Π΄ΠΎΠ±Π°Π²Π»ΡΠ΅ΠΌ Π½Π΅ ΠΊ ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½Π½ΡΠΌ
unappliedMigrations.Add(migration.Key, migration.Value);
}
}
// ΠΡΠ»ΠΈ targetMigration Π½Π΅ ΡΠΊΠ°Π·Π°Π½Π° ΡΠΎ Π² migrationsToApply Π»ΠΎΠΆΠΈΠΌ Π½Π΅ ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½Π½ΡΠ΅ ΠΌΠΈΠ³ΡΠ°ΡΠΈΠΈ
if (string.IsNullOrEmpty(targetMigration))
{
migrationsToApply = unappliedMigrations
.Select(p => _migrationsAssembly.CreateMigration(p.Value, _activeProvider))
.ToList();
migrationsToRevert = Array.Empty<Migration>();
}
else if (targetMigration == Migration.InitialDatabase)
{
migrationsToApply = Array.Empty<Migration>();
migrationsToRevert = appliedMigrations
.OrderByDescending(m => m.Key)
.Select(p => _migrationsAssembly.CreateMigration(p.Value, _activeProvider))
.ToList();
}
else
{ // Π Else ΡΠ»ΡΡΠ°Π΅ Π½Π°Ρ
ΠΎΠ΄ΠΈΠΌ targetMigration Π² Π½Π΅ΠΏΡΠΈΠΌΠ΅Π½Π΅Π½Π½ΡΡ
ΠΌΠΈΠ³ΡΠ°ΡΠΈΡΡ
ΠΈ Π»ΠΎΠΆΠΈΠΌ ΠΈΡ
Π² migrationsToApply
targetMigration = _migrationsAssembly.GetMigrationId(targetMigration);
migrationsToApply = unappliedMigrations
.Where(m => string.Compare(m.Key, targetMigration, StringComparison.OrdinalIgnoreCase) <= 0)
.Select(p => _migrationsAssembly.CreateMigration(p.Value, _activeProvider))
.ToList();
migrationsToRevert = appliedMigrations
.Where(m => string.Compare(m.Key, targetMigration, StringComparison.OrdinalIgnoreCase) > 0)
.OrderByDescending(m => m.Key)
.Select(p => _migrationsAssembly.CreateMigration(p.Value, _activeProvider))
.ToList();
}
}
2.The second question is similar to reloading assembly !
If it is not possible to reload asseblyes that stores model class, as i mentioned before!
Then it is possible to make models with dynamic injection in runtime, injection in dbcontext class ?
When litle time application go to service mode, and all models that changed (for example added one column)
all models are reloading and injecting in dbcontext ?
3.And last one!
I understand that many things in ef core realized with interface principals!
And if shall realize some custom Imigrator or IMigrationsAssembly how to make it work when many source files have no documentation and,
writed coments that api may changed ?
/// <summary>
/// This API supports the Entity Framework Core infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
/// </summary>
I wanna say that Ure have some plans to release more modern and fashionable things!
But where is border of source code, when api changeable or not gonna change in future?
Maybe must be some council(soviet) that shall approve architecture and future of EF CORE ?
I Could realize some library that will dependent on EF CORE but, there have some guarantee that feature that I realized will work in future releases of ef core ?
I wonder how coupled it really is... Have you tried just passing dummy reflection instances around?
class MyMigrationsAssembly : IMigrationsAssembly
{
class DummyTypeInfo : TypeInfo
{
public DummyTypeInfo(string migrationId)
{
MigrationId = migrationId
}
public string MigrationId { get; }
}
public IReadOnlyDictionary<string, TypeInfo> Migrations { get; }
= new Dictionary<string, TypeInfo>()
{
// TODO: Get this list from XML, etc.
["00000000000000_MyMigration"] = new DummyTypeInfo("00000000000000_MyMigration");
};
public Migration CreateMigration(TypeInfo migrationClass, string activeProvider)
{
var migrationId = ((DummyTypeInfo)migrationClass).MigrationId;
return new MyMigration(migrationId);
}
class MyMigration : Migration
{
string _id;
public MyMigration(string id)
{
_id = id;
}
protected override void Up(MigrationBuilder migrationBuilder)
{
// TODO: Deserialize migration operations from XML, etc.
}
}
}
Actually i want to use already ready types and classes , u just want is to do another storage for migration, all other componets of ef core still be in place !
I wanna say, is all i need is to deserilize MigrationComands from xml and aplly them !
@bricelam for now i dint try it, I am still diving in sources ! Tnks for example! The main actually problem that I need it not only for MS sql, i need it for other providers!
Is need not for 1 database.
This kind migration is depended on Ms sql specific
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
I'am trying to say when command add-migration executes.
Its code that generates is dependable on 1 database.
Maybe have some abstract class, not depend on specific RDBMS ?
With out .Annotation("SqlServer:ValueGenerationStrategy", or it is impossible ???
protected override void Up(MigrationBuilder migrationBuilder)
{
migrationBuilder.CreateTable(
name: "Authors",
columns: table => new
{
AuthorId = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
FirstName = table.Column<string>(nullable: true),
LastName = table.Column<string>(nullable: true)
},
constraints: table =>
{
table.PrimaryKey("PK_Authors", x => x.AuthorId);
});
migrationBuilder.CreateTable(
name: "Books",
columns: table => new
{
BookId = table.Column<int>(nullable: false)
.Annotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn),
Title = table.Column<string>(nullable: true),
AuthorId = table.Column<int>(nullable: false)
},
constraints: table =>
{
table.PrimaryKey("PK_Books", x => x.BookId);
table.ForeignKey(
name: "FK_Books_Authors_AuthorId",
column: x => x.AuthorId,
principalTable: "Authors",
principalColumn: "AuthorId",
onDelete: ReferentialAction.Cascade);
});
migrationBuilder.CreateIndex(
name: "IX_Books_AuthorId",
table: "Books",
column: "AuthorId");
}
Have you seen Migrations with Multiple Providers?
thanks for feedback !