Может ли EF Code First работать с LocalDB в приложении ClickOnce?
Итак, я пробую EF Code First, чтобы иметь возможность обновлять диск с кодом в базе данных. Я работаю над приложением ClickOnce с использованием LocalDB, поэтому решил, что это может быть лучшим решением для меня, так как в противном случае изменения в файле MDF приведут к его перезаписи на клиенте при развертывании, что приведет к потере всего введенного ранее.
Тем не менее, теперь у меня есть своя справедливая доля всех новых проблем, связанных с Code First Migrations. Я прошел Миграции Code First на MSDN, и мне удалось получить начальный Configuration
создан, а также начальное создание базы данных.
Проблемы начинаются, когда я пытаюсь осуществить свою первую настоящую миграцию. Я добавил одно поле в одну из своих моделей и попытался выполнить явную миграцию для обработки этого изменения схемы при следующей публикации. Что ж...
PM> Add-Migration AddIsPercentField
Невозможно сгенерировать явную миграцию, поскольку ожидаются следующие явные миграции: [201601052011180_InitialCreate]. Примените ожидающие явные миграции, прежде чем пытаться создать новую явную миграцию.
Хорошо, я запусту обновление и попробую еще раз:
PM> Обновление базы данных
Укажите флаг '-Verbose', чтобы просмотреть операторы SQL, применяемые к целевой базе данных.
Применение явных миграций: [201601052011180_InitialCreate].
Применение явной миграции: 201601052011180_InitialCreate.
Невозможно обновить базу данных в соответствии с текущей моделью, поскольку есть ожидающие изменения и автоматическая миграция отключена. Либо запишите ожидающие изменения модели в миграцию на основе кода, либо включите автоматическую миграцию. Установите в DbMigrationsConfiguration.AutomaticMigrationsEnabled значение true, чтобы включить автоматическую миграцию.
Вы можете использовать команду Add-Migration для записи ожидающих изменений модели в миграцию на основе кода.PM> Add-Migration AddIsPercentField
Невозможно сгенерировать явную миграцию, поскольку ожидаются следующие явные миграции: [201601052011180_InitialCreate]. Примените ожидающие явные миграции, прежде чем пытаться создать новую явную миграцию.
Это знакомо, так как это ошибка (откровенная ложь?), Которую я только что сказал ранее. Ну, может быть, если я отменю свои изменения и обновлю снова, он перейдет в правильное состояние:
PM> Обновление базы данных
Укажите флаг '-Verbose', чтобы просмотреть операторы SQL, применяемые к целевой базе данных.
Применение явных миграций: [201601052011180_InitialCreate].
Применение явной миграции: 201601052011180_InitialCreate.
Метод бегущего семени.
Хорошо, без предупреждения на этот раз. Должно быть золотым. Поле добавлено обратно, проект перестроен. Вот так:
PM> Add-Migration AddIsPercentField
Невозможно сгенерировать явную миграцию, поскольку ожидаются следующие явные миграции: [201601052011180_InitialCreate]. Примените ожидающие явные миграции, прежде чем пытаться создать новую явную миграцию.
Итак... есть ли на самом деле рабочий способ генерации явных миграций для любых изменений, кроме первого?
РЕДАКТИРОВАТЬ: я сделал некоторый прогресс в этом направлении, я считаю. Я заметил, что __MigrationHistory
таблица не была сгенерирована в моем.mdf после запуска Update-Database
, хотя он сказал, что все завершено просто отлично. Я считаю, что проблема заключается в том, как локальная база данных работает в приложении. Ссылки на строку подключения AttachDbFilename=|DataDirectory|
, Я думаю, что происходит то, что он временно развертывает.mdf, обновляет это временное развертывание, таким образом, в конечном счете, не фиксируя изменения.
Я работаю над решением, которое я имею в виду, - чтобы миграции работали с копией пустого файла.mdf, помещенного в статическое местоположение, так что статический файл.mdf будет использоваться для отслеживания и определения изменений, тогда как пустой.mdf будет то, что выходит клиентам с развертыванием.
1 ответ
Я обнаружил, что корень моей проблемы был в том, что консольные команды фактически не могли вносить изменения, таким образом, отслеживать миграции, в мой файл данных. Это было связано с тем, что строка подключения к файлу данных ссылалась на развернутое местоположение, поэтому обновляемый файл был просто временным.
Отчасти это было хорошо, потому что весь смысл использования Code First Migrations в моем проекте состоял в том, чтобы избежать изменения хэш-подписи в моем.mdf (который должен был просто оставаться пустым, в качестве заполнителя) при публикации, чтобы данные из предыдущих версий никогда не будет отменен и отброшен. Однако это также привело к очевидной (ретроспективно) проблеме, заключающейся в том, что EF не может отслеживать изменения из-за отсутствия __MigrationHistory
Таблица.
Решение, на котором я приехал, состояло в том, чтобы иметь два файла.mdf. Пустой, для развертываний, и второй, к которому я бы взаимодействовал с Code First Migrations. Итак, у меня есть начальный MyData.mdf
действия сборки Content
и второй MyDataDesignTime.mdf
действия сборки None
, (База данных миграции "Время разработки" не должна быть развернута.)
Используя этот подход, я обнаружил, что теперь могу успешно работать с миграциями, вызывая Update-Database
а также Add-Migration
, убедившись, что передали -ConnectionString
параметр с AttachDbFilename
указал на полный путь к моей базе данных времени проектирования.
Позже лень снабжать долго -ConnectionString
параметр в каждой команде миграции, я добавил путь времени разработки в мои строки подключения конфигурации и обновил мой DbContext
так что он изначально использует путь времени разработки, но который я бы изменил в начале времени выполнения, чтобы использовать мой фактический целевой файл данных:
public partial class MyData : DbContext
{
public const string DesignTimeConnection = "MyDataConnectionStringDesignTime";
public static string ConnectionName { get; set; } = DesignTimeConnection;
public MyData()
: base("name=" + ConnectionName)
{
}
...
}
И при инициализации приложения:
MyData.ConnectionName = "MyDataConnectionString";
Это работает, и это делает вещи проще для меня. Однако у меня осталась одна небольшая проблема: у меня есть полный статический путь, который применяется только к моей среде, оставленной в файле app.config. На данный момент это не проблема, так как я единственный разработчик в этом проекте, но я не доволен запахом кода. Есть ли какая-то переменная пути, которую я могу использовать, чтобы она по-прежнему указывала на фактические данные времени разработки (а не на временные развернутые файлы), но относилась ли она к активному открытому проекту?