Ядро Entity Framework: Безопасно ли удалять Migration.Designer.cs, если мы никогда не вернем миграцию?
У нас есть схема базы данных с ~200 таблицами. Снимок модели (Migration.Designer.cs), который создается для каждой миграции, составляет ~ 20 тыс. Строк. Таким образом, наличие большого количества миграций действительно замедляет нашу сборку на CI (при ~30 миграциях создание решения занимает 6 минут с миграциями или 4 минуты без них).
Итак, на вопрос: безопасно ли удалять снимки моделей для старых миграций (которые, как мы знаем, никогда не вернутся)? Используются ли снимки модели для чего-либо еще, кроме Revert-Migration?
5 ответов
Используются ли снимки модели для чего-либо еще, кроме Revert-Migration?
Да. Есть несколько крайних случаев, когда это необходимо. На SQL Server такие случаи:
- AlterColumn, когда столбец сужен или вычисленное выражение изменено, и индексы необходимо перестроить
- CreateIndex для таблицы, оптимизированной для памяти, когда индекс уникален и ссылается на обнуляемые столбцы
Таким образом, большую часть времени, вероятно, безопасно удалить, но, пожалуйста, проверьте, что ваши миграции все еще работают после этого.
У меня такая же проблема с моим текущим проектом. Более 400 переходов и 6 млн строк кода внутри.Designer. Вот как мне удалось решить эту проблему:
MigrationProject.csproj
<PropertyGroup>
...
<DefaultItemExcludes Condition="'$(Configuration)' == 'Debug' ">$(DefaultItemExcludes);Migrations\**\*.Designer.cs</DefaultItemExcludes>
</PropertyGroup>
Таким образом, вам не нужно ни сбрасывать миграцию, ни удалять файлы.Designer.
Изменить: это временное решение, вам нужно будет однажды сбросить свои миграции.
Это усовершенствованный подход Хайме Юла.
В процессе разработки я хочу иметь возможность протестировать мою текущую миграцию и выполнить миграции, которые попадают в мою ветку при слиянии других веток. Поэтому вместо того, чтобы исключать все файлы дизайнера, я сохраняю последние, например:
<PropertyGroup Condition="'$(Configuration)'=='DEBUG'">
<CurrentYear>$([System.DateTime]::Now.Year)</CurrentYear>
<CurrentMonth>$([System.DateTime]::Now.Month)</CurrentMonth>
<DefaultItemExcludes>$(DefaultItemExcludes);Migrations\*.Designer.cs</DefaultItemExcludes>
</PropertyGroup>
<ItemGroup>
<Compile Include="Migrations\$(CurrentYear)$(CurrentMonth)*.Designer.cs" />
</ItemGroup>
Конечно, чтобы быть полностью пуленепробиваемым, нужно было также включить месяц назад. Как это:
<PropertyGroup Condition="'$(Configuration)'=='DEBUG'">
<CurrentMonth>$([System.DateTime]::Now.Month)</CurrentMonth>
<YearOfCurrentMonth>$([System.DateTime]::Now.Year)</YearOfCurrentMonth>
<LastMonth>$([System.DateTime]::Now.AddMonths(-1).Month)</LastMonth>
<YearOfLastMonth>$([System.DateTime]::Now.AddMonths(-1).Year)</YearOfLastMonth>
<DefaultItemExcludes>$(DefaultItemExcludes);Migrations\*.Designer.cs</DefaultItemExcludes>
</PropertyGroup>
<ItemGroup>
<Compile Include="Migrations\$(YearOfCurrentMonth)$(CurrentMonth)*.Designer.cs" />
<Compile Include="Migrations\$(YearOfLastMonth)$(LastMonth)*.Designer.cs" />
</ItemGroup>
И последнее, но не менее важное: мы решили опустить
'$(Configuration)'=='DEBUG'
condition, поскольку мы только продвигаемся вперед в производстве, а для разработки мы используем EnsureCreated. Поэтому нет необходимости хранить историю всех миграций.
Файл .Designer.cs содержит разделяемый класс с двумя атрибутами:
[DbContext...
[Migration...
Не забудьте скопировать эти атрибуты в класс, содержащий ваш код миграции (методы Up и Down того же частичного класса).EF использует эти атрибуты, чтобы определить, какие миграции находятся в сборке.
После удаления файлов .Designer.cs из нашего проекта dbContext.Database.GetPendingMigrations().Count() вернул 0.
Мы решили эту проблему, добавив эти атрибуты.
Основываясь на ответах Хайме Юла , Деяна и Бриселама , я создал задачу MSBuild, которая пытается решить эту проблему автоматически. Все, что вам нужно сделать, это установить задачу.
Он автоматически перемещает эти атрибуты из файла в основной файл кода:
[DbContext...
[Migration...
Он устанавливает*.Designer.cs
файлы, которые не нужно компилировать:<DefaultItemExcludes>$(DefaultItemExcludes);**\*.Designer.cs</DefaultItemExcludes>
Затем он ищет последниеN
(настраиваемое количество) файлов *.Designer.cs и позволяет компилировать их с помощью<Compile Include="xxx" />
Установить:dotnet add package MSBuild.EntityFrameworkCore.RemoveDesignerCompilation --prerelease
(Вы должны использовать--prerelease
пока не будет опубликована стабильная версия. Сначала мне хотелось бы собрать отзывы о предварительном выпуске)