diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.InMemory/InMemoryConfigurator.cs b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.InMemory/InMemoryConfigurator.cs
new file mode 100644
index 0000000..0661311
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.InMemory/InMemoryConfigurator.cs
@@ -0,0 +1,28 @@
+
+using NonSucking.Framework.Extension.EntityFrameworkCore;
+using NonSucking.Framework.Extension.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore;
+
+namespace NonSucking.Framework.Extension.Database.InMemory;
+public class InMemoryConfigurator : IDatabaseConfigurator
+{
+ public string Name => "InMemory";
+ public class MigrationContext : MigrationDatabaseContext
+ {
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ _ = optionsBuilder.UseInMemoryDatabase("Empty");
+ base.OnConfiguring(optionsBuilder);
+ }
+ }
+
+ public IAutoMigrationContextBuilder GetEmptyForMigration()
+ {
+ return new MigrationContext();
+ }
+
+ public DbContextOptionsBuilder OnConfiguring(DbContextOptionsBuilder optionsBuilder, string connectionString)
+ {
+ return optionsBuilder.UseInMemoryDatabase(connectionString);
+ }
+}
diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.InMemory/NonSucking.Framework.Extension.Database.InMemory.csproj b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.InMemory/NonSucking.Framework.Extension.Database.InMemory.csproj
new file mode 100644
index 0000000..596520c
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.InMemory/NonSucking.Framework.Extension.Database.InMemory.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+ True
+
+
+
+
diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.InMemory/NonSucking.Framework.Extension.Database.InMemory.props.template b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.InMemory/NonSucking.Framework.Extension.Database.InMemory.props.template
new file mode 100644
index 0000000..3d98332
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.InMemory/NonSucking.Framework.Extension.Database.InMemory.props.template
@@ -0,0 +1,23 @@
+
+
+ ${VERSION_FULL}
+ ${VERSION_LONG}
+ ${AUTHORS}
+ ${COPYRIGHT}
+ ${COMPANY}
+ ${TITLE_INMEMORY}
+ ${DESCRIPTION_INMEMORY}
+
+ This is a first preview version and not intended for productive use. Not everything has been tested or commented yet.
+
+
+ ${TAGS_INMEMORY}
+
+
+ ${REPO_URL}
+ $(RepositoryUrl)
+ true
+ LICENSE
+ en-US
+
+
\ No newline at end of file
diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MSSQL/MSSQLConfigurator.cs b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MSSQL/MSSQLConfigurator.cs
new file mode 100644
index 0000000..fbbfc1b
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MSSQL/MSSQLConfigurator.cs
@@ -0,0 +1,29 @@
+
+using NonSucking.Framework.Extension.EntityFrameworkCore;
+using NonSucking.Framework.Extension.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore;
+
+namespace NonSucking.Framework.Extension.Database.MSSQL;
+public class MSSQLConfigurator : IDatabaseConfigurator
+{
+ public string Name => "MSSQL";
+ public class MigrationContext : MigrationDatabaseContext
+ {
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ _ = optionsBuilder.UseSqlServer();
+ base.OnConfiguring(optionsBuilder);
+ }
+
+ }
+
+ public IAutoMigrationContextBuilder GetEmptyForMigration()
+ {
+ return new MigrationContext();
+ }
+
+ public DbContextOptionsBuilder OnConfiguring(DbContextOptionsBuilder optionsBuilder, string connectionString)
+ {
+ return optionsBuilder.UseSqlServer(connectionString);
+ }
+}
diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MSSQL/NonSucking.Framework.Extension.Database.MSSQL.csproj b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MSSQL/NonSucking.Framework.Extension.Database.MSSQL.csproj
new file mode 100644
index 0000000..3286925
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MSSQL/NonSucking.Framework.Extension.Database.MSSQL.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+ True
+
+
+
+
diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MSSQL/NonSucking.Framework.Extension.Database.MSSQL.props.template b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MSSQL/NonSucking.Framework.Extension.Database.MSSQL.props.template
new file mode 100644
index 0000000..adfcbf7
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MSSQL/NonSucking.Framework.Extension.Database.MSSQL.props.template
@@ -0,0 +1,23 @@
+
+
+ ${VERSION_FULL}
+ ${VERSION_LONG}
+ ${AUTHORS}
+ ${COPYRIGHT}
+ ${COMPANY}
+ ${TITLE_MSSQL}
+ ${DESCRIPTION_MSSQL}
+
+ This is a first preview version and not intended for productive use. Not everything has been tested or commented yet.
+
+
+ ${TAGS_MSSQL}
+
+
+ ${REPO_URL}
+ $(RepositoryUrl)
+ true
+ LICENSE
+ en-US
+
+
\ No newline at end of file
diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MySql/MySQLConfigurator.cs b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MySql/MySQLConfigurator.cs
new file mode 100644
index 0000000..7f2d705
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MySql/MySQLConfigurator.cs
@@ -0,0 +1,30 @@
+
+using NonSucking.Framework.Extension.EntityFrameworkCore;
+using NonSucking.Framework.Extension.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore;
+
+namespace NonSucking.Framework.Extension.Database.MySql;
+public class MySQLConfigurator : IDatabaseConfigurator
+{
+ public string Name => "MySQL";
+ public class MigrationContext : MigrationDatabaseContext
+ {
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ _ = optionsBuilder.UseMySql("server=none;userid=none;password=none;database=none", ServerVersion.Create(10, 9, 3, Pomelo.EntityFrameworkCore.MySql.Infrastructure.ServerType.MariaDb));
+ base.OnConfiguring(optionsBuilder);
+ }
+
+ }
+
+ public IAutoMigrationContextBuilder GetEmptyForMigration()
+ {
+ return new MigrationContext();
+ }
+
+ public DbContextOptionsBuilder OnConfiguring(DbContextOptionsBuilder optionsBuilder, string connectionString)
+ {
+ return optionsBuilder.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString));
+ }
+}
+
diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MySql/NonSucking.Framework.Extension.Database.MySql.csproj b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MySql/NonSucking.Framework.Extension.Database.MySql.csproj
new file mode 100644
index 0000000..703a48f
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MySql/NonSucking.Framework.Extension.Database.MySql.csproj
@@ -0,0 +1,22 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+ True
+
+
+
+
diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MySql/NonSucking.Framework.Extension.Database.MySql.props.template b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MySql/NonSucking.Framework.Extension.Database.MySql.props.template
new file mode 100644
index 0000000..4441b0f
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.MySql/NonSucking.Framework.Extension.Database.MySql.props.template
@@ -0,0 +1,23 @@
+
+
+ ${VERSION_FULL}
+ ${VERSION_LONG}
+ ${AUTHORS}
+ ${COPYRIGHT}
+ ${COMPANY}
+ ${TITLE_MYSQL}
+ ${DESCRIPTION_MYSQL}
+
+ This is a first preview version and not intended for productive use. Not everything has been tested or commented yet.
+
+
+ ${TAGS_MYSQL}
+
+
+ ${REPO_URL}
+ $(RepositoryUrl)
+ true
+ LICENSE
+ en-US
+
+
\ No newline at end of file
diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.PostrgeSQL/NonSucking.Framework.Extension.Database.PostgreSQL.props.template b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.PostrgeSQL/NonSucking.Framework.Extension.Database.PostgreSQL.props.template
new file mode 100644
index 0000000..ec4acf7
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.PostrgeSQL/NonSucking.Framework.Extension.Database.PostgreSQL.props.template
@@ -0,0 +1,23 @@
+
+
+ ${VERSION_FULL}
+ ${VERSION_LONG}
+ ${AUTHORS}
+ ${COPYRIGHT}
+ ${COMPANY}
+ ${TITLE_POSTGRESQL}
+ ${DESCRIPTION_POSTGRESQL}
+
+ This is a first preview version and not intended for productive use. Not everything has been tested or commented yet.
+
+
+ ${TAGS_POSTGRESQL}
+
+
+ ${REPO_URL}
+ $(RepositoryUrl)
+ true
+ LICENSE
+ en-US
+
+
\ No newline at end of file
diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.PostrgeSQL/NonSucking.Framework.Extension.Database.PostrgeSQL.csproj b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.PostrgeSQL/NonSucking.Framework.Extension.Database.PostrgeSQL.csproj
new file mode 100644
index 0000000..c1866ab
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.PostrgeSQL/NonSucking.Framework.Extension.Database.PostrgeSQL.csproj
@@ -0,0 +1,23 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+
+
+
+
diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.PostrgeSQL/PostgresConfigurator.cs b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.PostrgeSQL/PostgresConfigurator.cs
new file mode 100644
index 0000000..7158acd
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.PostrgeSQL/PostgresConfigurator.cs
@@ -0,0 +1,28 @@
+
+using NonSucking.Framework.Extension.EntityFrameworkCore;
+using NonSucking.Framework.Extension.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore;
+
+namespace NonSucking.Framework.Extension.Database.PostrgeSQL;
+public class PostgresConfigurator : IDatabaseConfigurator
+{
+ public string Name => "PostrgeSQL";
+ public class MigrationContext : MigrationDatabaseContext
+ {
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ _ = optionsBuilder.UseNpgsql();
+ base.OnConfiguring(optionsBuilder);
+ }
+
+ }
+
+ public IAutoMigrationContextBuilder GetEmptyForMigration()
+ {
+ return new MigrationContext();
+ }
+ public DbContextOptionsBuilder OnConfiguring(DbContextOptionsBuilder optionsBuilder, string connectionString)
+ {
+ return optionsBuilder.UseNpgsql(connectionString);
+ }
+}
diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.Sqlite/NonSucking.Framework.Extension.Database.Sqlite.csproj b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.Sqlite/NonSucking.Framework.Extension.Database.Sqlite.csproj
new file mode 100644
index 0000000..7fb5cd3
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.Sqlite/NonSucking.Framework.Extension.Database.Sqlite.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net7.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+ True
+
+
+
+
diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.Sqlite/NonSucking.Framework.Extension.Database.Sqlite.props.template b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.Sqlite/NonSucking.Framework.Extension.Database.Sqlite.props.template
new file mode 100644
index 0000000..c283e3c
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.Sqlite/NonSucking.Framework.Extension.Database.Sqlite.props.template
@@ -0,0 +1,23 @@
+
+
+ ${VERSION_FULL}
+ ${VERSION_LONG}
+ ${AUTHORS}
+ ${COPYRIGHT}
+ ${COMPANY}
+ ${TITLE_SQLITE}
+ ${DESCRIPTION_SQLITE}
+
+ This is a first preview version and not intended for productive use. Not everything has been tested or commented yet.
+
+
+ ${TAGS_SQLITE}
+
+
+ ${REPO_URL}
+ $(RepositoryUrl)
+ true
+ LICENSE
+ en-US
+
+
\ No newline at end of file
diff --git a/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.Sqlite/SqLiteConfigurator.cs b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.Sqlite/SqLiteConfigurator.cs
new file mode 100644
index 0000000..22846e1
--- /dev/null
+++ b/EntityFrameworkExtension/NonSucking.Framework.Extension.Database.Sqlite/SqLiteConfigurator.cs
@@ -0,0 +1,30 @@
+
+using Microsoft.EntityFrameworkCore;
+
+using NonSucking.Framework.Extension.EntityFrameworkCore;
+using NonSucking.Framework.Extension.EntityFrameworkCore.Migrations;
+
+namespace NonSucking.Framework.Extension.Database.Sqlite;
+public class SqLiteConfigurator : IDatabaseConfigurator
+{
+ public string Name => "SQLite";
+
+ public class MigrationContext : MigrationDatabaseContext
+ {
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ _ = optionsBuilder.UseSqlite();
+ base.OnConfiguring(optionsBuilder);
+ }
+
+ }
+
+ public IAutoMigrationContextBuilder GetEmptyForMigration()
+ {
+ return new MigrationContext();
+ }
+ public DbContextOptionsBuilder OnConfiguring(DbContextOptionsBuilder optionsBuilder, string connectionString)
+ {
+ return optionsBuilder.UseSqlite(connectionString);
+ }
+}
diff --git a/NonSucking.Framework.Extension.EntityFrameworkCore/DatabaseContext.cs b/NonSucking.Framework.Extension.EntityFrameworkCore/DatabaseContext.cs
new file mode 100644
index 0000000..717ea0c
--- /dev/null
+++ b/NonSucking.Framework.Extension.EntityFrameworkCore/DatabaseContext.cs
@@ -0,0 +1,115 @@
+
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+using NonSucking.Framework.Extension.EntityFrameworkCore.Migrations;
+
+using System.Diagnostics.CodeAnalysis;
+using System.Reflection;
+using System.Runtime.Loader;
+
+namespace NonSucking.Framework.Extension.EntityFrameworkCore
+{
+
+ public abstract class DatabaseContext : DbContext, IAutoMigrationContext
+ {
+ public bool EnableUseLazyLoading { get; set; } = true;
+ public string AssemblyRootName { get; set; }
+ public bool AddAllEntities { get; set; }
+
+ protected DatabaseContext()
+ {
+ }
+
+ protected DatabaseContext(DbContextOptions options) : base(options)
+ {
+ }
+
+ protected DatabaseContext(bool enableUseLazyLoading, string assemblyRootName, bool addAllEntities)
+ {
+ EnableUseLazyLoading = enableUseLazyLoading;
+ AssemblyRootName = assemblyRootName;
+ AddAllEntities = addAllEntities;
+ }
+
+ public bool FindLastMigration(Type contextAttributeType, [MaybeNullWhen(false)] out Migration migration, [MaybeNullWhen(false)] out string id)
+ {
+ migration = null;
+ id = "";
+ TypeInfo? migrationType = null;
+ var assembly = Database.GetService();
+ var migrationsInDb = Database.GetAppliedMigrations().OrderByDescending(id => id);
+ foreach (var item in migrationsInDb)
+ {
+ if (assembly.Migrations.TryGetValue(item, out migrationType))
+ {
+ id = item;
+ break;
+ }
+ }
+
+ if (string.IsNullOrWhiteSpace(id) || migrationType is null)
+ return false;
+
+ migration = (Migration)Activator.CreateInstance(migrationType)!;
+
+ return true;
+ }
+
+ protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
+ {
+ optionsBuilder.UseLazyLoadingProxies(EnableUseLazyLoading);
+ base.OnConfiguring(optionsBuilder);
+ }
+
+ static Type[] onModelCreatingMethodTypes = new[] { typeof(ModelBuilder) };
+ protected override void OnModelCreating(ModelBuilder modelBuilder)
+ {
+ if (AddAllEntities)
+ {
+
+ foreach (var type in AssemblyLoadContext
+ .Default
+ .Assemblies
+ .Where(x => string.IsNullOrWhiteSpace(AssemblyRootName)
+ || x.FullName.Contains(AssemblyRootName))
+ .SelectMany(x => x.GetTypes())
+ .Where(type => !type.IsAbstract
+ && !type.IsInterface
+ && typeof(IEntity).IsAssignableFrom(type))
+ .Where(x => x.Namespace is not null && !x.Namespace.Contains("Migration")))
+ {
+ if (modelBuilder.Model.FindEntityType(type) is null)
+ {
+ _ = modelBuilder.Model.AddEntityType(type);
+ }
+ var method = type.GetMethod(nameof(OnModelCreating), System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public, onModelCreatingMethodTypes);
+ if (method is not null)
+ method.Invoke(null, new[] { modelBuilder });
+ }
+ }
+
+ base.OnModelCreating(modelBuilder);
+ }
+ ///
+ /// Migrates with a transaction
+ ///
+ /// Applies any pending migrations for the context to the database. Will create the database
+ /// if it does not already exist.
+ ///
+ ///
+ /// Note that this API is mutually exclusive with . EnsureCreated does not use migrations
+ /// to create the database and therefore the database that is created cannot be later updated using migrations.
+ ///
+ ///
+ ///
+ /// See Database migrations for more information.
+ ///
+ /// The for the context.
+ public void Migrate()
+ {
+ Database.Migrate();
+ }
+ }
+}
diff --git a/NonSucking.Framework.Extension.EntityFrameworkCore/DatabaseFactory.cs b/NonSucking.Framework.Extension.EntityFrameworkCore/DatabaseFactory.cs
new file mode 100644
index 0000000..fde33a8
--- /dev/null
+++ b/NonSucking.Framework.Extension.EntityFrameworkCore/DatabaseFactory.cs
@@ -0,0 +1,52 @@
+using System.Reflection;
+using System.Runtime.Loader;
+
+namespace NonSucking.Framework.Extension.EntityFrameworkCore
+{
+
+ public static class DatabaseFactory
+ {
+ private static AssemblyLoadContext? assemblyLoadContext;
+
+ public static List DatabaseConfigurators { get; } = new();
+
+ ///
+ /// Needs to be called, so that the are filled
+ ///
+ /// Path to the dll which contains the implementation(s)
+ public static void Initialize(string source)
+ {
+ if (DatabaseConfigurators.Any(x => source.Contains(x.Name, StringComparison.OrdinalIgnoreCase)))
+ return;
+
+ if (assemblyLoadContext is null)
+ {
+ assemblyLoadContext = AssemblyLoadContext.GetLoadContext(typeof(IDatabaseConfigurator).Assembly);
+ assemblyLoadContext.Resolving += Default_Resolving;
+ }
+ var fullName = new FileInfo(source).FullName;
+ var databasePlugin = assemblyLoadContext.LoadFromAssemblyPath(fullName);
+
+ //Get All IDatabaseConfigurator
+ DatabaseConfigurators
+ .AddRange(databasePlugin
+ .GetTypes()
+ .Where(x => x.IsAssignableTo(typeof(IDatabaseConfigurator)) && x.GetConstructor(Array.Empty()) != null)
+ .Select(x => (IDatabaseConfigurator)Activator.CreateInstance(x)));
+ }
+
+ private static Assembly? Default_Resolving(AssemblyLoadContext context, AssemblyName name)
+ {
+ if (name.Name?.EndsWith("resources") ?? false)
+ return null;
+
+ var existing = context.Assemblies.FirstOrDefault(x => x.FullName == name.FullName);
+ if (existing is not null)
+ return existing;
+ string assemblyPath = new FileInfo($"{name.Name}.dll").FullName;
+ if (assemblyPath is not null)
+ return context.LoadFromAssemblyPath(assemblyPath);
+ return null;
+ }
+ }
+}
diff --git a/NonSucking.Framework.Extension.EntityFrameworkCore/IDatabaseConfigurator.cs b/NonSucking.Framework.Extension.EntityFrameworkCore/IDatabaseConfigurator.cs
new file mode 100644
index 0000000..0c49054
--- /dev/null
+++ b/NonSucking.Framework.Extension.EntityFrameworkCore/IDatabaseConfigurator.cs
@@ -0,0 +1,13 @@
+using Microsoft.EntityFrameworkCore;
+
+using NonSucking.Framework.Extension.EntityFrameworkCore.Migrations;
+
+namespace NonSucking.Framework.Extension.EntityFrameworkCore
+{
+ public interface IDatabaseConfigurator
+ {
+ string Name { get; }
+ DbContextOptionsBuilder OnConfiguring(DbContextOptionsBuilder optionsBuilder, string connectionString);
+ IAutoMigrationContextBuilder GetEmptyForMigration();
+ }
+}
diff --git a/NonSucking.Framework.Extension.EntityFrameworkCore/IEntity.cs b/NonSucking.Framework.Extension.EntityFrameworkCore/IEntity.cs
new file mode 100644
index 0000000..181d264
--- /dev/null
+++ b/NonSucking.Framework.Extension.EntityFrameworkCore/IEntity.cs
@@ -0,0 +1,7 @@
+namespace NonSucking.Framework.Extension.EntityFrameworkCore
+{
+ public interface IEntity
+ {
+
+ }
+}
diff --git a/NonSucking.Framework.Extension.EntityFrameworkCore/MigrationDatabaseContext.cs b/NonSucking.Framework.Extension.EntityFrameworkCore/MigrationDatabaseContext.cs
new file mode 100644
index 0000000..46985c4
--- /dev/null
+++ b/NonSucking.Framework.Extension.EntityFrameworkCore/MigrationDatabaseContext.cs
@@ -0,0 +1,41 @@
+
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Metadata.Conventions.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Migrations.Operations;
+
+using NonSucking.Framework.Extension.EntityFrameworkCore.Migrations;
+
+namespace NonSucking.Framework.Extension.EntityFrameworkCore
+{
+ public abstract class MigrationDatabaseContext : DbContext, IAutoMigrationContextBuilder
+ {
+ public ModelBuilder CreateBuilder()
+ {
+ var dependencies = Database.GetService();
+ var setBuilder = Database.GetService();
+ var serviceProvider = Database.GetService();
+ var modelConfigurationBuilder =
+ new ModelConfigurationBuilder(setBuilder.CreateConventionSet(), serviceProvider);
+
+ return modelConfigurationBuilder.CreateModelBuilder(dependencies);
+ }
+
+ public IModel FinalizeModel(IModel model)
+ {
+ var initializer = Database.GetService();
+ return initializer.Initialize(model);
+ }
+
+ public IReadOnlyList GenerateDiff(IModel? source, IModel? target)
+ {
+ var sourceModel = source?.GetRelationalModel();
+ var targetModel = target?.GetRelationalModel();
+
+ var differ = Database.GetService();
+ return differ.GetDifferences(sourceModel, targetModel);
+ }
+ }
+}
diff --git a/NonSucking.Framework.Extension.EntityFrameworkCore/Migrations/IAutoMigrationContext.cs b/NonSucking.Framework.Extension.EntityFrameworkCore/Migrations/IAutoMigrationContext.cs
new file mode 100644
index 0000000..4cfc194
--- /dev/null
+++ b/NonSucking.Framework.Extension.EntityFrameworkCore/Migrations/IAutoMigrationContext.cs
@@ -0,0 +1,20 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Migrations.Operations;
+
+using System.Diagnostics.CodeAnalysis;
+
+namespace NonSucking.Framework.Extension.EntityFrameworkCore.Migrations;
+
+public interface IAutoMigrationContextBuilder
+{
+ IModel FinalizeModel(IModel model);
+ IReadOnlyList GenerateDiff(IModel? source, IModel? target);
+ ModelBuilder CreateBuilder();
+}
+
+public interface IAutoMigrationContext
+{
+ bool FindLastMigration(Type contextAttributeType, [MaybeNullWhen(false)] out Migration migration, [MaybeNullWhen(false)] out string id);
+}
\ No newline at end of file
diff --git a/NonSucking.Framework.Extension.EntityFrameworkCore/Migrations/IAutoMigrationTypeProvider.cs b/NonSucking.Framework.Extension.EntityFrameworkCore/Migrations/IAutoMigrationTypeProvider.cs
new file mode 100644
index 0000000..6fca5f3
--- /dev/null
+++ b/NonSucking.Framework.Extension.EntityFrameworkCore/Migrations/IAutoMigrationTypeProvider.cs
@@ -0,0 +1,6 @@
+namespace NonSucking.Framework.Extension.EntityFrameworkCore.Migrations;
+
+public interface IAutoMigrationTypeProvider
+{
+ IReadOnlyList GetEntityTypes();
+}
\ No newline at end of file
diff --git a/NonSucking.Framework.Extension.EntityFrameworkCore/Migrations/ModelMigration.cs b/NonSucking.Framework.Extension.EntityFrameworkCore/Migrations/ModelMigration.cs
new file mode 100644
index 0000000..28b211b
--- /dev/null
+++ b/NonSucking.Framework.Extension.EntityFrameworkCore/Migrations/ModelMigration.cs
@@ -0,0 +1,85 @@
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Metadata;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+using System.Reflection;
+
+namespace NonSucking.Framework.Extension.EntityFrameworkCore.Migrations;
+
+public static class ModelMigration
+{
+ public static void BuildVersion(this ModelBuilder modelBuilder, string version)
+ {
+
+ }
+
+ public static void BuildVersion(this ModelBuilder modelBuilder, IAutoMigrationTypeProvider typeProvider)
+ {
+ //TODO: Solution required our table names are property names from the context
+ foreach (var type in typeProvider.GetEntityTypes())
+ {
+ if (modelBuilder.Model.FindEntityType(type) is null)
+ _ = modelBuilder.Model.AddEntityType(type);
+ }
+ }
+
+ public static void SetUpgradeOperations(this MigrationBuilder migrationBuilder, Migration migration)
+ {
+ IAutoMigrationContextBuilder providerContextBuilder;
+ IModel target, source;
+ GetMigrationClasses(migration, out providerContextBuilder, out target, out source);
+
+ var diff = providerContextBuilder.GenerateDiff(source, target);
+ migrationBuilder.Operations.AddRange(diff);
+ }
+ public static void SetDowngradeOperations(this MigrationBuilder migrationBuilder, Migration migration)
+ {
+ IAutoMigrationContextBuilder providerContextBuilder;
+ IModel target, source;
+ GetMigrationClasses(migration, out providerContextBuilder, out target, out source);
+
+ var diff = providerContextBuilder.GenerateDiff(target, source);
+ migrationBuilder.Operations.AddRange(diff);
+ }
+
+ private static void GetMigrationClasses(Migration migration, out IAutoMigrationContextBuilder providerContextBuilder, out IModel target, out IModel? source)
+ {
+ providerContextBuilder = DatabaseFactory.DatabaseConfigurators.First().GetEmptyForMigration();
+ var migrationType = migration.GetType();
+ var contextAttribute = migrationType.GetCustomAttribute() ?? throw new ArgumentNullException();
+ var currentContext = (IAutoMigrationContext)Activator.CreateInstance(contextAttribute.ContextType)!;
+
+ var targetBuilder = providerContextBuilder.CreateBuilder();
+
+ if (migration is IAutoMigrationTypeProvider autoTypeProvider)
+ {
+ targetBuilder.BuildVersion(autoTypeProvider);
+ }
+ else
+ {
+ var idAttribute = migrationType.GetCustomAttribute() ??
+ throw new ArgumentNullException();
+
+ targetBuilder.BuildVersion(idAttribute.Id);
+ }
+
+ target = providerContextBuilder.FinalizeModel((IModel)targetBuilder.Model);
+ source = null;
+ if (currentContext.FindLastMigration(contextAttribute.ContextType, out var lastMigration, out var lastMigrationId))
+ {
+ var sourceBuilder = providerContextBuilder.CreateBuilder();
+
+ if (lastMigration is IAutoMigrationTypeProvider lastTypeProvider)
+ {
+ sourceBuilder.BuildVersion(lastTypeProvider);
+ }
+ else
+ {
+ sourceBuilder.BuildVersion(lastMigrationId);
+ }
+
+ source = providerContextBuilder.FinalizeModel((IModel)sourceBuilder.Model);
+ }
+ }
+}
diff --git a/NonSucking.Framework.Extension.EntityFrameworkCore/NonSucking.Framework.Extension.EntityFrameworkCore.csproj b/NonSucking.Framework.Extension.EntityFrameworkCore/NonSucking.Framework.Extension.EntityFrameworkCore.csproj
new file mode 100644
index 0000000..b87f850
--- /dev/null
+++ b/NonSucking.Framework.Extension.EntityFrameworkCore/NonSucking.Framework.Extension.EntityFrameworkCore.csproj
@@ -0,0 +1,24 @@
+
+
+
+
+ false
+ net6.0
+ enable
+ enable
+ en
+ LICENSE
+
+
+
+
+ True
+
+
+
+
+
+
+
+
+
diff --git a/NonSucking.Framework.Extension.EntityFrameworkCore/NonSucking.Framework.Extension.EntityFrameworkCore.props.template b/NonSucking.Framework.Extension.EntityFrameworkCore/NonSucking.Framework.Extension.EntityFrameworkCore.props.template
new file mode 100644
index 0000000..6f6434d
--- /dev/null
+++ b/NonSucking.Framework.Extension.EntityFrameworkCore/NonSucking.Framework.Extension.EntityFrameworkCore.props.template
@@ -0,0 +1,23 @@
+
+
+ ${VERSION_FULL}
+ ${VERSION_LONG}
+ ${AUTHORS}
+ ${COPYRIGHT}
+ ${COMPANY}
+ ${TITLE_ENTITYFRAMEWORKCORE}
+ ${DESCRIPTION_ENTITYFRAMEWORKCORE}
+
+ This is a first preview version and not intended for productive use. Not everything has been tested or commented yet.
+
+
+ ${TAGS_ENTITYFRAMEWORKCORE}
+
+
+ ${REPO_URL}
+ $(RepositoryUrl)
+ true
+ LICENSE
+ en-US
+
+
\ No newline at end of file
diff --git a/NonSucking.Framework.Extension.sln b/NonSucking.Framework.Extension.sln
index bf7d0a5..07f9793 100644
--- a/NonSucking.Framework.Extension.sln
+++ b/NonSucking.Framework.Extension.sln
@@ -21,6 +21,20 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NonSucking.Framework.Serial
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DEMO.Base", "DEMO.Base\DEMO.Base.csproj", "{B1A1B2D7-A54A-4FDE-BED9-48DCB702F418}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NonSucking.Framework.Extension.EntityFrameworkCore", "NonSucking.Framework.Extension.EntityFrameworkCore\NonSucking.Framework.Extension.EntityFrameworkCore.csproj", "{9531439E-BA92-4457-A30C-6C707DEE4EF6}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "EntityFrameworkExtension", "EntityFrameworkExtension", "{88C91CBB-4FFD-4A3E-BD44-FFDC1C202BE6}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NonSucking.Framework.Extension.Database.InMemory", "EntityFrameworkExtension\NonSucking.Framework.Extension.Database.InMemory\NonSucking.Framework.Extension.Database.InMemory.csproj", "{E1DEA45A-A4BB-4A88-8FD9-20061CD3B014}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NonSucking.Framework.Extension.Database.MSSQL", "EntityFrameworkExtension\NonSucking.Framework.Extension.Database.MSSQL\NonSucking.Framework.Extension.Database.MSSQL.csproj", "{ED5663F3-A355-4586-A30A-68E6CE3F2FC7}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NonSucking.Framework.Extension.Database.MySql", "EntityFrameworkExtension\NonSucking.Framework.Extension.Database.MySql\NonSucking.Framework.Extension.Database.MySql.csproj", "{56EBC6DE-7D58-4FB9-B696-28C4C7335A97}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NonSucking.Framework.Extension.Database.PostrgeSQL", "EntityFrameworkExtension\NonSucking.Framework.Extension.Database.PostrgeSQL\NonSucking.Framework.Extension.Database.PostrgeSQL.csproj", "{0DD295C6-648C-4D8F-8FC8-942959D5A007}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NonSucking.Framework.Extension.Database.Sqlite", "EntityFrameworkExtension\NonSucking.Framework.Extension.Database.Sqlite\NonSucking.Framework.Extension.Database.Sqlite.csproj", "{65FA58CE-BD18-45F3-9A70-B500D419C45D}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -63,10 +77,41 @@ Global
{B1A1B2D7-A54A-4FDE-BED9-48DCB702F418}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B1A1B2D7-A54A-4FDE-BED9-48DCB702F418}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B1A1B2D7-A54A-4FDE-BED9-48DCB702F418}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9531439E-BA92-4457-A30C-6C707DEE4EF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9531439E-BA92-4457-A30C-6C707DEE4EF6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9531439E-BA92-4457-A30C-6C707DEE4EF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9531439E-BA92-4457-A30C-6C707DEE4EF6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E1DEA45A-A4BB-4A88-8FD9-20061CD3B014}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E1DEA45A-A4BB-4A88-8FD9-20061CD3B014}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E1DEA45A-A4BB-4A88-8FD9-20061CD3B014}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E1DEA45A-A4BB-4A88-8FD9-20061CD3B014}.Release|Any CPU.Build.0 = Release|Any CPU
+ {ED5663F3-A355-4586-A30A-68E6CE3F2FC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {ED5663F3-A355-4586-A30A-68E6CE3F2FC7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {ED5663F3-A355-4586-A30A-68E6CE3F2FC7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {ED5663F3-A355-4586-A30A-68E6CE3F2FC7}.Release|Any CPU.Build.0 = Release|Any CPU
+ {56EBC6DE-7D58-4FB9-B696-28C4C7335A97}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {56EBC6DE-7D58-4FB9-B696-28C4C7335A97}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {56EBC6DE-7D58-4FB9-B696-28C4C7335A97}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {56EBC6DE-7D58-4FB9-B696-28C4C7335A97}.Release|Any CPU.Build.0 = Release|Any CPU
+ {0DD295C6-648C-4D8F-8FC8-942959D5A007}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {0DD295C6-648C-4D8F-8FC8-942959D5A007}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {0DD295C6-648C-4D8F-8FC8-942959D5A007}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {0DD295C6-648C-4D8F-8FC8-942959D5A007}.Release|Any CPU.Build.0 = Release|Any CPU
+ {65FA58CE-BD18-45F3-9A70-B500D419C45D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {65FA58CE-BD18-45F3-9A70-B500D419C45D}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {65FA58CE-BD18-45F3-9A70-B500D419C45D}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {65FA58CE-BD18-45F3-9A70-B500D419C45D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
+ GlobalSection(NestedProjects) = preSolution
+ {E1DEA45A-A4BB-4A88-8FD9-20061CD3B014} = {88C91CBB-4FFD-4A3E-BD44-FFDC1C202BE6}
+ {ED5663F3-A355-4586-A30A-68E6CE3F2FC7} = {88C91CBB-4FFD-4A3E-BD44-FFDC1C202BE6}
+ {56EBC6DE-7D58-4FB9-B696-28C4C7335A97} = {88C91CBB-4FFD-4A3E-BD44-FFDC1C202BE6}
+ {0DD295C6-648C-4D8F-8FC8-942959D5A007} = {88C91CBB-4FFD-4A3E-BD44-FFDC1C202BE6}
+ {65FA58CE-BD18-45F3-9A70-B500D419C45D} = {88C91CBB-4FFD-4A3E-BD44-FFDC1C202BE6}
+ EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {2938EA08-9C94-425B-81F3-434AF51FFBCE}
EndGlobalSection