Может ли 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. На данный момент это не проблема, так как я единственный разработчик в этом проекте, но я не доволен запахом кода. Есть ли какая-то переменная пути, которую я могу использовать, чтобы она по-прежнему указывала на фактические данные времени разработки (а не на временные развернутые файлы), но относилась ли она к активному открытому проекту?

Другие вопросы по тегам