I'd like to amend the SQL that's being generated by EF:CF when generating the database schema (DDL), as suggested by the Entity Framework team.
How can this be done?
I couldn't find anything appropriate via Google.
I'd like to amend the SQL that's being generated by EF:CF when generating the database schema (DDL), as suggested by the Entity Framework team.
How can this be done?
I couldn't find anything appropriate via Google.
You can override the
MigrationSqlGenerator
that is used by Entity Framework by calling the DbMigrationsConfiguration.SetSqlGenerator() method in the constructor of yourDbMigrationsConfiguration
class, passing the database provider name (e.g."System.Data.SqlClient"
for SQL Server), and theMigrationSqlGenerator
instance to use for that database provider.Consider the example from the work item that you linked to:
Suppose that the table for
MyEntity
had already been generated and theAdd-Migration
command was used to add theName
field.By default, the scaffolded migration is:
Notice that the scaffolder did not generate anything for the
MinLengthAttribute
.To have EF convey the minimum length requirement, you can specify an attribute-to-column annotation convention. As mentioned on that documentation page, any
AnnotationValues
are ignored by the default SQL generators.Within your DbContext's OnModelCreating() override, add the following:
After adding that, you can regenerate the scaffolded migration by running
Add-Migration -Force AddMyEntity_Name
. Now the scaffolded migration is:Suppose that, as in the linked work item, you want to generate a constraint to check that the trimmed
Name
value is greater than the minLength (5 in this case).You can start by creating a custom
MigrationSqlGenerator
that extendsSqlServerMigrationSqlGenerator
and call SetSqlGenerator() to install the customMigrationSqlGenerator
:Right now, this
CustomSqlServerMigrationSqlGenerator
overrides the Generate(AddColumnOperation) method, but simply calls the base implementation.If you look at the documentation of
AddColumnOperation
, you will see two important properties,Column
andTable
.Column
is theColumnModel
that was created by the lambda in Up(),c => c.String(nullable: false, annotations: ...)
.In the Generate() method, you can access the custom
AnnotationValues
via theAnnotations
property of theColumnModel
.To generate the DDL that adds the constraint, you need to generate the SQL and call the Statement() method. For example:
If you run
Update-Database -Verbose
, you will see an exception generated byCustomSqlServerMigrationSqlGenerator
:To fix this issue, specify a defaultValue in the Up() method that is longer than the minimum length (e.g.
"unknown"
):Now if you re-run
Update-Database -Verbose
, you will see theALTER TABLE
statement that adds the column and theALTER TABLE
statement that adds the constraint:See also: EF6: Writing Your Own Code First Migration Operations, which shows how to implement a custom migration operation.