2012-04-28 16 views
7

Sono appena iniziato con Entity Framework (4.3.1) e sto creando un modello code-first con ereditarietà TPT utilizzando il provider di MySQL EF (6.5.4). Quando si tenta di creare la struttura del database, sto ricevendo un MySQLException "Identifier name 'LongClassNameOne_TypeConstraint_From_ClassName2s_To_LongClassNameOnes' is too long" (Questa è la relazione che si riferisce tavolo della classe derivata al tavolo della classe genitore.)Identificatore generato troppo lungo per il nome del vincolo

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() 
    ... 

Come posso controllare questo nome per renderlo più breve, o forzare il taglio al limite del nome di 64 caratteri o qualcosa del genere?

+0

Problema grave. Non riesco a rispondere alla domanda, ma per SQL Server non ho mai visto un modo per controllare e personalizzare i nomi dei vincoli. Non sono nemmeno sicuro di chi sia il responsabile e chi sia la colpa del nome: Entity Framework o il provider MySQL? – Slauma

+0

Non ho un ambiente di fronte a me - ma questo potrebbe essere d'aiuto (se potessi averne bisogno ne posterò una risposta più tardi oggi) - http://msdn.microsoft.com/en-us/library/hh829636 (v = vs.103) .aspx - ed eventualmente questo link - http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/2b182758-ef29-4407-b62b-12aee816aa45. Ad esempio, è possibile impostare il proprio 'SqlGenerator' e poi ci sono delle sostituzioni per varie parti di generazione SQL - ma non sono sicuro che questo copra ciò di cui hai bisogno. – NSGaga

+0

@NSGaga - Se si sovrascrive SqlGenerator e si cambiano i nomi, il database potrebbe non corrispondere mai al modello generato da CodeFirst e si potrebbero incontrare molti problemi strani che saranno difficili da risolvere. – Pawel

risposta

5

È necessario utilizzare il nome della tabella più breve in quanto non è possibile configurare i nomi dei vincoli. Si noti che non è necessario modificare i nomi delle classi per farlo. È possibile utilizzare l'attributo Table o utilizzare il metodo .ToTable() in OnModelCreating.

+0

Ho pubblicato la soluzione effettiva che avevo in mente - il link stava indicando erroneamente il cambio di tabella (dato che ero di fretta da un dispositivo) - ma quello che intendevo è cambiare il nome della relazione - che non dovrebbe avere conseguenze. La mappatura dei nomi delle tabelle è ancora la soluzione più semplice - completamente d'accordo (+1) - se desiderabile. – NSGaga

+0

Ho scelto di specificare un nome di tabella più breve tramite l'attributo di annotazione. Questo tipo puzza però, dal momento che questo progetto coinvolge una libreria di base utilizzata da altre persone. È fastidioso dover ricorrere a questo. I miei nomi delle tabelle non sono nemmeno così lunghi ... –

5

Per espandere il mio commento in precedenza su ...

Se si può solo cambiare il nome della tabella - poi andare con la mappatura del OnModelCreating - as @Pawel suggested, questa è probabilmente la soluzione più semplice di tutti.

Tuttavia, se si desidera cambiare solo il nome della relazione,

... fornendo un personalizzato SqlGenerator (cioè il SqlServerMigrationSqlGenerator) nella Configuration() è possibile micro-gestire l'SQL effettivo generato quando necessario (e potrebbe essere la soluzione generica e automatizzata in alcuni casi generali). per esempio.

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 qualcosa del genere (è necessario far corrispondere, trovare la giusta denominazione -. O confrontare la Name Length e accorciarlo dove necessario e nella configurazione (file generato dalle migrazioni) ...

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

(nota: non so che cosa è il nome del provider di MySQL)

... questo dovrebbe cambiare l'FK del rapporto - e per quanto potrebbe verificare questa veloce funziona bene, come il il nome della relazione non è realmente usato nel modello da C# (solo un nome db normalmente).

+0

Grazie per la risposta dettagliata, ma penso che accorgerò semplicemente i nomi dei tavoli e vivrò con esso.Speravo che un'altra soluzione potesse essere quella di abbreviare quel nome, ma sembra che questo sia nel codice EF, non nel provider MySQL. Se si trovasse nel provider MySQL, avrei optato per tale percorso, poiché ho già avuto bisogno di correggere altri 2 bug nel provider per farlo funzionare. –

+0

np - è più facile che io sia d'accordo - il posto giusto per sistemare le "relazioni troppo lunghe" sarebbe intorno alla generazione di codice sql (dato che EF/CF genera quei nomi troppo lunghi per MySQL), quindi la colpa di MySQL è che non può accettare quegli identificatori, ma EF lo sta 'causando'). Non ho avuto il tuo ragionamento sopra. Ma sceglierei la 'facile via d'uscita' (i nomi delle tabelle), e ricorrere alla riparazione della generazione SQL se si ripete nel tempo. – NSGaga

+0

Il nome del generatore MySQL è 'MySqlMigrationSqlGenerator' –

Problemi correlati