2012-04-28 20 views
7

Estoy empezando con Entity Framework (4.3.1) y estoy haciendo un modelo de primer código con herencia TPT utilizando el proveedor de EF de MySQL (6.5.4). Al intentar crear la estructura de base de datos, estoy recibiendo un MySQLException "Identifier name 'LongClassNameOne_TypeConstraint_From_ClassName2s_To_LongClassNameOnes' is too long" (Esta es la relación que relaciona la mesa de la clase derivada a la mesa de la clase padre.)Identificador generado demasiado largo para el nombre de restricción

at MySql.Data.MySqlClient.MySqlStream.ReadPacket() 
    at MySql.Data.MySqlClient.NativeDriver.GetResult(Int32& affectedRow, Int32& insertedId) 
    at MySql.Data.MySqlClient.Driver.GetResult(Int32 statementId, Int32& affectedRows, Int32& insertedId) 
    at MySql.Data.MySqlClient.Driver.NextResult(Int32 statementId, Boolean force) 
    at MySql.Data.MySqlClient.MySqlDataReader.NextResult() 
    at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader(CommandBehavior behavior) 
    at MySql.Data.MySqlClient.MySqlCommand.ExecuteReader() 
    at MySql.Data.MySqlClient.MySqlCommand.ExecuteNonQuery() 
    at MySql.Data.MySqlClient.MySqlScript.Execute() 
    at MySql.Data.MySqlClient.MySqlProviderServices.DbCreateDatabase(DbConnection connection, Nullable`1 commandTimeout, StoreItemCollection storeItemCollection) 
    at System.Data.Objects.ObjectContext.CreateDatabase() 
    at System.Data.Entity.Internal.DatabaseOperations.Create(ObjectContext objectContext) 
    at System.Data.Entity.Internal.DatabaseCreator.CreateDatabase(InternalContext internalContext, Func`3 createMigrator, ObjectContext objectContext) 
    at System.Data.Entity.Internal.InternalContext.CreateDatabase(ObjectContext objectContext) 
    at System.Data.Entity.Database.Create() 
    at System.Data.Entity.DropCreateDatabaseAlways`1.InitializeDatabase(TContext context) 
    at System.Data.Entity.Database.<>c__DisplayClass2`1.<SetInitializerInternal>b__0(DbContext c) 
    at System.Data.Entity.Internal.InternalContext.<>c__DisplayClass8.<PerformDatabaseInitialization>b__6() 
    at System.Data.Entity.Internal.InternalContext.PerformInitializationAction(Action action) 
    at System.Data.Entity.Internal.InternalContext.PerformDatabaseInitialization() 
    at System.Data.Entity.Internal.LazyInternalContext.<InitializeDatabase>b__4(InternalContext c) 
    at System.Data.Entity.Internal.RetryAction`1.PerformAction(TInput input) 
    at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabaseAction(Action`1 action) 
    at System.Data.Entity.Internal.LazyInternalContext.InitializeDatabase() 
    at System.Data.Entity.Internal.InternalContext.Initialize() 
    at System.Data.Entity.Internal.InternalContext.ForceOSpaceLoadingForKnownEntityTypes() 
    at System.Data.Entity.DbContext.System.Data.Entity.Infrastructure.IObjectContextAdapter.get_ObjectContext() 
    ... 

¿Cómo puedo controlar este nombre para que sea más corto, o obligarlo a recortar el límite de nombre de 64 caracteres, o algo así?

+0

Problema malvado. No puedo responder la pregunta, pero para SQL Server nunca he visto una forma de controlar y personalizar los nombres de las restricciones. Incluso no estoy seguro de quién es responsable y de quién es el culpable del nombre: Entity Framework en sí o el proveedor de MySQL. – Slauma

+0

No tengo un entorno en frente mío, pero esto podría ayudar (si es posible que necesite más, publicaré una respuesta más adelante) - http://msdn.microsoft.com/en-us/library/hh829636 (v = vs.103) .aspx - y posiblemente este enlace - http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/2b182758-ef29-4407-b62b-12aee816aa45. es decir, podría establecer su propio 'SqlGenerator' y luego hay sustituciones para varias partes de generación de SQL, pero no estoy seguro si esto cubre lo que necesita. – NSGaga

+0

@NSGaga - Si sobrescribe SqlGenerator y cambia los nombres, es posible que su base de datos nunca coincida con el modelo generado por CodeFirst y puede encontrarse con muchos problemas extraños que serán difíciles de resolver. – Pawel

Respuesta

5

Debe utilizar el nombre de la tabla más corta, ya que no hay forma de configurar los nombres de las restricciones. Tenga en cuenta que no necesita cambiar los nombres de clase para hacer eso. Puede usar el atributo Table o usar el método .ToTable() en OnModelCreating.

+0

Publiqué la solución real que tenía en mente: el enlace apuntaba erróneamente al cambio de tabla (ya que tenía prisa desde un dispositivo), pero lo que quise decir es cambiar el nombre de la relación, que no debería tener consecuencias. El mapeo de nombre de tabla es la solución más fácil aún, totalmente de acuerdo (+1), si es deseable. – NSGaga

+0

Elegí especificar un nombre de tabla más corto a través del atributo de anotación. Sin embargo, esto apesta, ya que este proyecto involucra una biblioteca base que otras personas usan. Es molesto tener que recurrir a esto. Los nombres de mi tabla no son realmente tan largos ... –

5

Para ampliar mi comentario anterior sobre ...

Si sólo puede cambiar el nombre de la tabla - y luego ir con la asignación en el OnModelCreating - as @Pawel suggested, eso es probablemente la solución más fácil de todos.

Sin embargo, si desea cambiar sólo el nombre de la relación,

... proporcionando una costumbre SqlGenerator (es decir, el SqlServerMigrationSqlGenerator) en el Configuration() puede micro-administrar el SQL real que se genera cuando necesaria (y esa podría ser la solución genérica y automatizada en algún caso general). p.ej.

public class MySqlGenerator : SqlServerMigrationSqlGenerator 
{ 
    protected override void Generate(AddForeignKeyOperation addForeignKeyOperation) 
    { 
     if (addForeignKeyOperation.Name == "LongClassNameOne_TypeConstraint_From_ClassName2s_To_LongClassNameOnes") 
      addForeignKeyOperation.Name = "MyCustomFKName"; 
     // addForeignKeyOperation.Name = "Test" + addForeignKeyOperation.Name; 
     base.Generate(addForeignKeyOperation); 
    } 
} 

... o algo por el estilo (que necesita para que coincida, encontrar el derecho de nombrar -. O comparar la Name Length y acortarlo cuando sea necesario y en su configuración (archivo generado por migraciones) ...

public Configuration() 
{ 
    AutomaticMigrationsEnabled = false; 
    SetSqlGenerator("MySQL provider??", new MySqlGenerator()); 
    // SetSqlGenerator("System.Data.SqlClient", new MySqlGenerator()); 
} 

(nota: no sé cuál es el nombre del proveedor de MySQL)

... esto debe cambiar el FK de la relación - y por lo que podría poner a prueba esta rápida funciona bien, como el El nombre de relación realmente no se usa en el modelo de C# (solo un nombre de db normalmente).

+0

Gracias por la respuesta detallada, pero creo que acortaré los nombres de las tablas y viviré con ellas.Esperaba que otra solución pudiera ser acortar ese nombre, pero parece que está en el código EF, no en el proveedor MySQL. Si estuviera en el proveedor de MySQL, habría elegido esa ruta, porque ya he necesitado reparar otros 2 errores en el proveedor para que funcione. –

+0

np -eso es más fácil, estoy de acuerdo- el lugar correcto para arreglar "relaciones demasiado largas" sería alrededor de la generación de código sql (ya que EF/CF genera esos nombres que son demasiado largos para MySQL), así que la falla de MySQL es que no puede aceptar esos identificadores, pero EF lo está 'causando'). No obtuve tu razonamiento arriba. Pero escogería la 'salida más fácil' (nombres de tabla), y recurriría a la reparación de la generación sql si lo repite con el tiempo. – NSGaga

+0

El nombre del generador de MySQL es 'MySqlMigrationSqlGenerator' –

Cuestiones relacionadas