2012-04-28 2 views
7

Я только начинаю с Entity Framework (4.3.1) и создаю первую кодовую модель с наследованием TPT с использованием поставщика MySQL EF (6.5.4). При попытке создать структуру базы данных, Я получаю MySQLException "Identifier name 'LongClassNameOne_TypeConstraint_From_ClassName2s_To_LongClassNameOnes' is too long" (Это отношение, которое относится таблица производного класса для таблицы родительского класса.)Сгенерированный идентификатор слишком длинный для имени ограничения

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

Как я могу контролировать это имя, чтобы сделать его короче, или заставить его подрезать до 64-символьного лимита имени или что-то в этом направлении?

+0

Зло проблема. Я не могу ответить на этот вопрос, но для SQL Server я никогда не видел способа контролировать и настраивать имена ограничений. Я даже не уверен, кто несет ответственность и кто виноват в имени: Entity Framework сам или поставщик MySQL? – Slauma

+0

У меня нет среды передо мной - но это может помочь (если вам может понадобиться больше, я отправлю ответ позже сегодня) - http://msdn.microsoft.com/en-us/library/hh829636 (v = vs.103) .aspx - и, возможно, эта ссылка - http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/2b182758-ef29-4407-b62b-12aee816aa45. т. е. вы можете установить свой собственный 'SqlGenerator', а затем есть переопределения для различных частей генерации SQL, но я не уверен, охватывает ли это то, что вам нужно. – NSGaga

+0

@NSGaga - Если вы перезаписываете SqlGenerator и меняете имена, ваша база данных может никогда не соответствовать модели, сгенерированной CodeFirst, и вы можете столкнуться с множеством странных проблем, которые трудно решить. – Pawel

ответ

5

Вам нужно использовать сокращенное имя таблицы, так как нет способа настроить имена ограничений. Обратите внимание: для этого вам не нужно менять имена классов. Вы можете использовать атрибут Table или использовать метод ToTable() в OnModelCreating.

+0

Я разместил фактическое решение, которое я имел в виду - ссылка неправильно указывала на изменение таблицы (поскольку я спешил с устройства), но я имел в виду изменение имени отношения, которое не должно иметь последствий. Отображение имен таблиц - это самое простое решение по-прежнему - полностью согласен (+1) - если желательно. – NSGaga

+0

Я решил указать более короткое имя таблицы с помощью атрибута аннотации. Тем не менее, это воняет, поскольку этот проект включает базовую библиотеку, которую используют другие люди. Это раздражает необходимость прибегать к этому. Мои имена таблиц на самом деле не все так долго .... –

5

Чтобы развернуть на мой комментарий раньше ...

Если вы можете просто изменить название таблицы - затем с отображением в OnModelCreating - as @Pawel suggested, что, скорее всего, самое простое решение всех.

Однако, если вы хотите изменить только имя отношения,

... путем предоставления пользовательских SqlGenerator (т.е. SqlServerMigrationSqlGenerator) в Configuration() вы можете микроуправление фактического SQL генерируется при (и это может быть общее автоматизированное решение в каком-то общем случае). например

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); 
    } 
} 

... или что-то вдоль этих линий (вы должны соответствовать, найти право называть. - или сравнить Name Length и сократить его, где это необходимо и в вашей конфигурации (файл генерируется миграции) ...

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

(примечание: я не знаю, что это имя провайдера для MySQL)

... это должно изменить FK в отношении - и, насколько мог проверить это быстро он работает нормально, как имя отношения на самом деле не используется в модели с C# (обычно это имя db).

+0

Спасибо за подробный ответ, но я думаю, что я просто сокращу имена таблиц и буду жить с ним.Я надеялся, что другим решением может быть сокращение этого имени, но похоже, что это код EF, а не поставщик MySQL. Если бы это было в MySQL-провайдере, я бы отправился туда, потому что мне уже нужно было исправить 2 других ошибки в провайдере, чтобы заставить это работать. –

+0

np - это проще, я согласен - правильное место для исправления слишком длинных отношений будет вокруг генерации кода sql (поскольку EF/CF генерирует те имена, которые слишком длинны для MySQL, похоже, так что ошибка MySQL заключается в том, что он не может принять эти идентификаторы, но EF «вызывает» его). Я не понял ваши рассуждения выше. Но я бы выбрал «простой выход» (имена таблиц) и прибегнуть к исправлению генерации sql, если у вас это повторяется с течением времени. – NSGaga

+0

Имя генератора MySQL - 'MySqlMigrationSqlGenerator' –

Смежные вопросы