16

We have our own external convention of naming objects and I need to change the naming convention for the auto generated foreign key constraints. Now it looks like: FK_dbo.City_dbo.CityType_City_CityTypeId but I would like it to be called City_FKC_CityType.

I found a similar question which says that you can change the name of constraints manually. However, this does not suit me, since I have a lot of tables and foreign key constraints.

I found some information about "Custom Code First Conventions" and I am wondering if I can change the name of constraint using this or if there are any methods to implement it?

Another variant is download the source code of EF, make changes and use that but that is in case of emergency.

As a side note, I would also like to change the naming convention of the primary key.

Community
  • 1
  • 1
Roman Marusyk
  • 23,328
  • 24
  • 73
  • 116
  • 1
    Your copious use of bold and italics makes my eyes hurt! Also, in what way does the solution in that answer not suit? It's pretty simple. – DavidG Jul 21 '15 at 09:22
  • Ok, I changed it :). I have too many tables and each table has a few constraint. It will take a long time to change a name for each foreign key – Roman Marusyk Jul 21 '15 at 09:30

1 Answers1

15

You can implement a custom sql generator class derived from SqlServerMigrationSqlGenerator from System.Data.Entity.SqlServer namespace:

public class CustomSqlGenerator : SqlServerMigrationSqlGenerator
{
    protected override void Generate(AddForeignKeyOperation addForeignKeyOperation)
    {
        addForeignKeyOperation.Name = getFkName(addForeignKeyOperation.PrincipalTable,
            addForeignKeyOperation.DependentTable, addForeignKeyOperation.DependentColumns.ToArray());
        base.Generate(addForeignKeyOperation);
    }

    protected override void Generate(DropForeignKeyOperation dropForeignKeyOperation)
    {
        dropForeignKeyOperation.Name = getFkName(dropForeignKeyOperation.PrincipalTable,
            dropForeignKeyOperation.DependentTable, dropForeignKeyOperation.DependentColumns.ToArray());
        base.Generate(dropForeignKeyOperation);
    }

    private static string getFkName(string primaryKeyTable, string foreignKeyTable, params string[] foreignTableFields)
    {
        // Return any format you need
    }
}

Then you need to register your generator in DbContext using DbConfiguration:

public class CustomDbConfiguration : DbConfiguration
{
    public CustomDbConfiguration()
    {
        SetMigrationSqlGenerator(SqlProviderServices.ProviderInvariantName,
            () => new CustomSqlGenerator());
    }
}

And DbConfigurationTypeAttribute:

[DbConfigurationType(typeof(CustomDbConfiguration))]
public class YourEntities : DbContext

UPDATE: If you want to change a primary key name, you need to override following Generate methods:

protected override void Generate(CreateTableOperation createTableOperation) 
{
    createTableOperation.PrimaryKey.Name = getPkName(createTableOperation.Name);
    base.Generate(createTableOperation);
}

protected override void Generate(AddPrimaryKeyOperation addPrimaryKeyOperation)
{
    addPrimaryKeyOperation.Name = getPkName(addPrimaryKeyOperation.Table);
    base.Generate(addPrimaryKeyOperation);
}

protected override void Generate(DropPrimaryKeyOperation dropPrimaryKeyOperation)
{
    dropPrimaryKeyOperation.Name = getPkName(dropPrimaryKeyOperation.Table);
    base.Generate(dropPrimaryKeyOperation);
}
  • Thank you very much. This is what I need, you really helped me. Thanks again – Roman Marusyk Jul 22 '15 at 18:31
  • And small question: I'm trying to do that for primary key as well, but something wrong. I overrided the `void Generate(AddPrimaryKeyOperation addPrimaryKeyOperation)` and implemented. Could you please suggest me why the my method never run when creating PK? Thx – Roman Marusyk Jul 22 '15 at 21:40
  • 1
    `AddPrimaryKeyOperation` generation is fired when you add a primary key to existing entity. Most of the time `CreateTableOperation` generation is used. – at least 3 and no more than 30 Jul 23 '15 at 04:56
  • Do you have any theory as to why this isn't working for me? I'm using the MSSQL provider and I've wired everything up as advised, but a quick logging statement reveals that `GetFkName()` is never hit. – InteXX Dec 26 '19 at 23:42