1

Initially our solution had System.Data.Entity.Infrastructure.LocalDbConnectionFactory set as the defaultConnectionFactory type in our web.config.

<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
  <parameters>
    <parameter value="v11.0" />
  </parameters>

I'm not sure we really need it like that since we use local SQL Server for dev and SQL Azure for real deployments. We use EF Code First and our tables get created with keys named like PK_dbo.Customers and FK_dbo.Customers_dbo.Employers_EmployerID and an index is created for each foreign key like IX_EmployerID.

We have switched to a custom connectionfactory based on the ideas in this post for a ReliableDbProvider created by Robert Moore because we want to have built in retry logic for transient failures with SQL Azure. It seems to work fine but it also seems like it causes the keys to be named differently (PK__Customer__A4AE64B8BB3388DF, Customer_Employer) and indexes to not be generated.

I didn't expect the factory to influence the generation. Any idea how it contributes?

After reflecting some code, seems like it has to do with the way the DbMigrationsConfiguration class which is used inside the DropCreateDatabaseIfModelChanges initializer works so we'll have to see if that can be overridden somehow.

public DbMigrationsConfiguration()
{
this.SetSqlGenerator("System.Data.SqlClient", new SqlServerMigrationSqlGenerator());
this.SetSqlGenerator("System.Data.SqlServerCe.4.0", new SqlCeMigrationSqlGenerator());
this.CodeGenerator = new CSharpMigrationCodeGenerator();
}

Still open to ideas!

Community
  • 1
  • 1
Bryan
  • 857
  • 1
  • 11
  • 25
  • Commenting out the defaultConnectionFactory from the config also results in well named indexes and keys just as if the LocalDbConnectionFactory is used. It's the default, right? Looking into more reflected code, it seems like it comes down to the DbProviderServices class that ends up getting used so still trying to dig in to understand what is being used in that case. – Bryan Sep 16 '13 at 14:06
  • Setting defaultFactory to “System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework” also works with the proper index and fk names I want. My provider is internally just wrapping this factory. I don't see where this factory or anything related to it should cause the index and keys to be named like this. – Bryan Sep 16 '13 at 15:03

1 Answers1

0

Based on some reflected code, it looks like the issue is that there is hardcoded logic for non-System.Data.SqlClient or sqlce providers in DatabaseCreator class that forces the generation down a different path.

public void CreateDatabase(InternalContext internalContext, Func<DbMigrationsConfiguration, DbContext, DbMigrator> createMigrator, ObjectContext objectContext)
    {
        if (internalContext.CodeFirstModel == null || !(internalContext.ProviderName == "System.Data.SqlClient") && !(internalContext.ProviderName == "System.Data.SqlServerCe.4.0"))
        {
            internalContext.DatabaseOperations.Create(objectContext);
            internalContext.SaveMetadataToDatabase();
        }
        else
        {
            Type type = internalContext.Owner.GetType();
            DbMigrationsConfiguration dbMigrationsConfiguration = new DbMigrationsConfiguration();
            dbMigrationsConfiguration.ContextType = type;
            dbMigrationsConfiguration.AutomaticMigrationsEnabled = true;
            dbMigrationsConfiguration.MigrationsAssembly = type.Assembly;
            dbMigrationsConfiguration.MigrationsNamespace = type.Namespace;
            dbMigrationsConfiguration.TargetDatabase = new DbConnectionInfo(internalContext.OriginalConnectionString, internalContext.ProviderName);
            createMigrator(dbMigrationsConfiguration, internalContext.Owner).Update();
        }
        internalContext.MarkDatabaseInitialized();
    }

In the end, we updated our datacontext constructor so that the DefaultConnectionFactory is set in code and not in config. In development (debug mode) only, if db doesn't exist, we set first to the SqlConnectionFactory since it generates the db with indexes and better naming that we want. After that or in release mode we want to use the custom provider which has retry logic we want.

Bryan
  • 857
  • 1
  • 11
  • 25