MigrationBuilder API를 사용하여, custom operations을 정의할 수 있다. API를 확장하기 위한 2가지 방법이 있다.
Sql() 함수를 사용하거나, custom MigrationOperation objects를 정의할 수 있다.
migrations에서 다음의 code를 사용해서 database user를 생성하는 operation을 각각의 방법으로 구현해보자.
migrationBuilder.CreateUser("SQLUser1", "Password");
Using MigrationBuilder.Sql()
custom operation 구현의 가장 쉬운 방법은 MigrationBuilder.Sql()를 호출하는 extension method를 정의하는 것이다.
public static OperationBuilder<SqlOperation> CreateUser(
this MigrationBuilder migrationBuilder,
string name,
string password)
=> migrationBuilder.Sql($"CREATE USER {name} WITH PASSWORD '{password}';");
여러개의 db providers를 지원해야 한다면, MigrationBuilder.ActiveProvider property를 사용할 수 있다. 다음과 같이, MS SQL과 PostgreSQL을 지원할 수 있다.
public static OperationBuilder<SqlOperation> CreateUser(
this MigrationBuilder migrationBuilder,
string name,
string password)
{
switch (migrationBuilder.ActiveProvider)
{
case "Npgsql.EntityFrameworkCore.PostgreSQL":
return migrationBuilder
.Sql($"CREATE USER {name} WITH PASSWORD '{password}';");
case "Microsoft.EntityFrameworkCore.SqlServer":
return migrationBuilder
.Sql($"CREATE USER {name} WITH PASSWORD = '{password}';");
}
throw new Exception("Unexpected provider.");
}
custom operation이 적용되어야 하는 모든 provider를 알고 있을 때 유효하다.
Using a MigrationOperation
custom operation을 SQL과 분리시키기 위해서, MigrationOperation을 직접 정의할 수 있다.
public class CreateUserOperation : MigrationOperation
{
public string Name { get; set; }
public string Password { get; set; }
}
With this approach, the extension method just needs to add one of these operations to MigrationBuilder.Operations.
이 방법으로, 확장 함수는 단지 MigrationBuilder.Operations.에 추가되기만 하면 된다.
public static OperationBuilder<CreateUserOperation> CreateUser(
this MigrationBuilder migrationBuilder,
string name,
string password)
{
var operation = new CreateUserOperation { Name = name, Password = password };
migrationBuilder.Operations.Add(operation);
return new OperationBuilder<CreateUserOperation>(operation);
}
이 방법은, 각 provider가 이 operation을 위해 어떻게 SQL을 생성해야 하는지 알아야 한다. 새로운 operation을 다루기 위해, SQL Server's generator를 overrideing한다.
public class MyMigrationsSqlGenerator : SqlServerMigrationsSqlGenerator
{
public MyMigrationsSqlGenerator(
MigrationsSqlGeneratorDependencies dependencies,
ICommandBatchPreparer commandBatchPreparer)
: base(dependencies, commandBatchPreparer)
{
}
protected override void Generate(
MigrationOperation operation,
IModel model,
MigrationCommandListBuilder builder)
{
if (operation is CreateUserOperation createUserOperation)
{
Generate(createUserOperation, builder);
}
else
{
base.Generate(operation, model, builder);
}
}
private void Generate(
CreateUserOperation operation,
MigrationCommandListBuilder builder)
{
var sqlHelper = Dependencies.SqlGenerationHelper;
var stringMapping = Dependencies.TypeMappingSource.FindMapping(typeof(string));
builder
.Append("CREATE USER ")
.Append(sqlHelper.DelimitIdentifier(operation.Name))
.Append(" WITH PASSWORD = ")
.Append(stringMapping.GenerateSqlLiteral(operation.Password))
.AppendLine(sqlHelper.StatementTerminator)
.EndCommand();
}
}
기본 migration sql generator service를 업데이트 된 것으로 대체한다.
protected override void OnConfiguring(DbContextOptionsBuilder options)
=> options
.UseSqlServer(_connectionString)
.ReplaceService<IMigrationsSqlGenerator, MyMigrationsSqlGenerator>();
'Entity Framework Core' 카테고리의 다른 글
Entity Framework Core] Reverse engineering (scaffolding) (0) | 2023.07.25 |
---|---|
.NET CLI] .NET 7, Entity Framework Core 오프라인 설치 (0) | 2023.07.21 |
Entity Framework Core] 팀 개발 환경에서 Migrations (0) | 2023.07.20 |
Entity Framework Core] Migrations 반영 (0) | 2023.07.20 |
Entity Framework Core] Migrations 관리 (0) | 2023.07.20 |
댓글