Last active
September 14, 2023 06:09
-
-
Save mszynka/4c9de68991080268959d03df26acdeef to your computer and use it in GitHub Desktop.
EF Core - Create table if not exists
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.EntityFrameworkCore.Migrations.Operations; | |
namespace Gist.Extensions.Sql | |
{ | |
internal sealed class CreateTableIfNotExistsOperation : CreateTableOperation | |
{ | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics.CodeAnalysis; | |
using System.Reflection; | |
using Microsoft.EntityFrameworkCore.Infrastructure; | |
using Microsoft.EntityFrameworkCore.Metadata; | |
using Microsoft.EntityFrameworkCore.Migrations; | |
using Microsoft.EntityFrameworkCore.Migrations.Operations; | |
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; | |
namespace Gist.Extensions.Sql | |
{ | |
public sealed class CustomMigrationsSqlGenerator : SqliteMigrationsSqlGenerator | |
{ | |
public CustomMigrationsSqlGenerator( | |
MigrationsSqlGeneratorDependencies dependencies, | |
IRelationalAnnotationProvider migrationsAnnotations) | |
: base(dependencies, | |
migrationsAnnotations) | |
{ | |
} | |
protected override void Generate( | |
MigrationOperation operation, | |
IModel model, | |
MigrationCommandListBuilder builder) | |
{ | |
if (operation is CreateTableIfNotExistsOperation createTableIfNotExistsOperation) | |
{ | |
Generate(createTableIfNotExistsOperation, model, builder); | |
} | |
else | |
{ | |
base.Generate(operation, model, builder); | |
} | |
} | |
private void Generate(CreateTableIfNotExistsOperation operation, IModel model, MigrationCommandListBuilder builder, | |
bool terminate = true) | |
{ | |
builder | |
.Append("CREATE TABLE IF NOT EXISTS ") | |
.Append(Dependencies.SqlGenerationHelper.DelimitIdentifier(operation.Name, operation.Schema)) | |
.AppendLine(" ("); | |
using (builder.Indent()) | |
{ | |
CreateTableColumns(operation, model, builder); | |
CreateTableConstraints(operation, model, builder); | |
builder.AppendLine(); | |
} | |
builder.Append(")"); | |
if (terminate) | |
{ | |
builder.AppendLine(Dependencies.SqlGenerationHelper.StatementTerminator); | |
EndStatement(builder); | |
} | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Microsoft.EntityFrameworkCore; | |
using Microsoft.EntityFrameworkCore.Migrations; | |
namespace Gist.Extensions.Sql | |
{ | |
public class GistDbContext : DbContext { | |
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) { | |
optionsBuilder | |
.UseSqlite($"Data Source={path};") | |
.ReplaceService<IMigrationsSqlGenerator, CustomMigrationsSqlGenerator>(); //This line is required | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Diagnostics.CodeAnalysis; | |
using System.Reflection; | |
using Microsoft.EntityFrameworkCore.Infrastructure; | |
using Microsoft.EntityFrameworkCore.Metadata; | |
using Microsoft.EntityFrameworkCore.Migrations; | |
using Microsoft.EntityFrameworkCore.Migrations.Operations; | |
using Microsoft.EntityFrameworkCore.Migrations.Operations.Builders; | |
namespace Gist.Extensions.Sql | |
{ | |
public static class MigrationExtensions | |
{ | |
public static CreateTableBuilder<TColumns> CreateTableIfNotExists<TColumns>( | |
this MigrationBuilder migrationBuilder, | |
[NotNull] string name, | |
[NotNull] Func<ColumnsBuilder, TColumns> columns, | |
string schema = null, | |
Action<CreateTableBuilder<TColumns>> constraints = null, | |
string comment = null) | |
{ | |
var createTableOperation = new CreateTableIfNotExistsOperation | |
{ | |
Schema = schema, | |
Name = name, | |
Comment = comment | |
}; | |
var columnsBuilder = new ColumnsBuilder(createTableOperation); | |
var columnsObject = columns(columnsBuilder); | |
var columnMap = new Dictionary<PropertyInfo, AddColumnOperation>(); | |
foreach (var property in typeof(TColumns).GetTypeInfo().DeclaredProperties) | |
{ | |
var addColumnOperation = ((IInfrastructure<AddColumnOperation>)property.GetMethod.Invoke(columnsObject, null)) | |
.Instance; | |
if (addColumnOperation.Name == null) | |
{ | |
addColumnOperation.Name = property.Name; | |
} | |
columnMap.Add(property, addColumnOperation); | |
} | |
var builder = new CreateTableBuilder<TColumns>(createTableOperation, columnMap); | |
constraints?.Invoke(builder); | |
migrationBuilder.Operations.Add(createTableOperation); | |
return builder; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment