Entity Framework автоматически переименовывает таблицы "многие ко многим" без каких-либо изменений.
Я работаю в том же проекте почти полтора года, и сегодня, когда я хотел добавить изменение в базу данных (сначала код), внезапная миграция EF хочет переименовать множество таблиц "многие ко многим", которые существуют в База данных сегодня. Эти имена таблиц не менялись более 2 лет, и я не могу понять, почему EF хочет их переименовать. Я проверил файлы сущностей, на которые указывает миграция, и нет изменений в файлах, которые могли бы объяснить это. В этом проекте мы работаем с аннотациями данных, поэтому мы никогда не давали никаких имен таблицам "многие ко многим", мы просто позволяем EF устанавливать имена таблиц. Любая помощь приветствуется!
RenameTable(name: "dbo.FilterLocation", newName: "LocationFilter");
RenameTable(name: "dbo.FilterCluster", newName: "ClusterFilter");
RenameTable(name: "dbo.ProfileFilter", newName: "FilterProfile");
RenameTable(name: "dbo.HtmlTemplateFilterProfile", newName: "ProfileHtmlTemplateFilter");
RenameTable(name: "dbo.HtmlTemplateProfile", newName: "ProfileHtmlTemplate");
RenameTable(name: "dbo.CategoryHtmlTemplateFilter", newName: "HtmlTemplateFilterCategory");
RenameTable(name: "dbo.HtmlTemplateCategory", newName: "CategoryHtmlTemplate");
DropPrimaryKey("dbo.LocationFilter");
DropPrimaryKey("dbo.ClusterFilter");
DropPrimaryKey("dbo.FilterProfile");
DropPrimaryKey("dbo.ProfileHtmlTemplateFilter");
DropPrimaryKey("dbo.ProfileHtmlTemplate");
DropPrimaryKey("dbo.HtmlTemplateFilterCategory");
DropPrimaryKey("dbo.CategoryHtmlTemplate");
AddPrimaryKey("dbo.LocationFilter", new[] { "Location_LocationId", "Filter_FilterId" });
AddPrimaryKey("dbo.ClusterFilter", new[] { "Cluster_ClusterId", "Filter_FilterId" });
AddPrimaryKey("dbo.FilterProfile", new[] { "Filter_FilterId", "Profile_ProfileId" });
AddPrimaryKey("dbo.ProfileHtmlTemplateFilter", new[] { "Profile_ProfileId", "HtmlTemplateFilter_HtmlTemplateFilterId" });
AddPrimaryKey("dbo.ProfileHtmlTemplate", new[] { "Profile_ProfileId", "HtmlTemplate_HtmlTemplateId" });
AddPrimaryKey("dbo.HtmlTemplateFilterCategory", new[] { "HtmlTemplateFilter_HtmlTemplateFilterId", "Category_CategoryId" });
AddPrimaryKey("dbo.CategoryHtmlTemplate", new[] { "Category_CategoryId", "HtmlTemplate_HtmlTemplateId" });
* edit. Изменения, которые я сделал, были следующими:
AddColumn("dbo.HtmlAdField", "MediaFactConnection", c => c.Int(nullable: false));
AddColumn("dbo.HtmlAd", "FactId", c => c.Int());
CreateIndex("dbo.HtmlAd", "FactId");
AddForeignKey("dbo.HtmlAd", "FactId", "dbo.Fact", "FactId");
DropColumn("dbo.HtmlAdField", "ConnectionState");
1 ответ
Для всех, кто наткнулся на этот пост...
Вопреки моему первоначальному комментарию, моя проблема не была решена путем запуска миграции в том виде, в каком она была сгенерирована. Я узнал, почему происходит такое поведение, как его исправить, и с самого начала извлек урок о том, как настраивать мои сущности.
Зачем?
Entity Framework будет называть и конфигурировать соединительные таблицы в зависимости от порядка, в котором его алгоритм конфигурирует сущности. Порядок, в котором DbSet<>
а также modelBuilder
"определения" появляются изменения, какая таблица слева / справа для соединительных таблиц. Я не могу точно определить, какое / как это повлияет на сгенерированный код, но в моем случае все это стало грушевидным после всеохватывающего Resharper 'Code Cleanup'.
Как исправить
Настроив явное сопоставление "многие ко многим", вы можете имитировать поведение генерации EF при первом создании таблиц.
Эта статья подтолкнула меня на правильный путь: создание отношений "многие ко многим" с использованием Fluent API в Entity Framework
В моем случае EF пытался переименовать таблицу RoleCategory в CategoryRole (и потерпел неудачу). Это было дополнение, которое я сделал:
modelBuilder.Entity<Role>()
.HasMany(e => e.Categories)
.WithMany(e => e.Roles)
.Map(m =>
{
m.ToTable("RoleCategory");
});
Заметки
Сконфигурируйте "от" сущность, которая названа первой в имени вашей таблицы. например для моего стола RoleCategory
Я сделал это:
Entity<Role>.HasMany(e => e.Categories)
не
Entity<Category>.HasMany(e => e.Roles)
Включить явное .WithMany(e => e.Roles)
который называет свойство навигации на другой стороне.
использование .Map()
указать имя таблицы. В моем случае, после ссылки не удалось, когда я указал имена столбцов с .MapLeftKey()
а также .MapRightKey()
,
По сути, я просто должен был продолжать играть с определением и работать add-migration
каждый раз, пока все манипуляции с таблицей исчезли из сгенерированного DbMigration
файл.
Мой урок
Очевидно, что наилучшей практикой является настройка всех отношений "многие ко многим" в явном виде с самого начала. В моем случае я не внес изменений ни в одну из сущностей, участвующих в соединительной таблице. Тем не менее, изменение в отдаленной сущности "двоюродного брата" и некоторая переупорядоченность DbContext привели меня в замешательство на некоторое время.
Урок выучен. Надеюсь, кому-то это тоже пригодится.