Обновление ClickOnce, контроль скачков версий

У нас есть развернутое приложение ClickOnce. Мы хотели бы убедиться, что установки обновляют только 1 версию каждый раз. (Другие передовые решения также приветствуются).

Скажем, например, у пользователя установлена ​​версия 1.16, в то же время было выпущено 2 новых выпуска, поэтому версия на сервере теперь 1.18. Мы хотели бы убедиться, что при следующем обновлении приложения оно сначала обновится с 1.16 до 1.17. Затем при следующем обновлении обновляется с 1.17 до 1.18 и т.д. Т.е. он не обновляется напрямую с 1.16 до 1.18.

Почему, спросите вы. Ну, это связано с тем, что наше приложение имеет локальную (SQL EXPRESS) базу данных. У нас есть собственный класс обновления, который вызывается при запуске приложения. Он определяет, произошло ли обновление CO, и если да, то обновляет локальную базу данных любыми изменениями схемы, которые могли быть сделаны. т.е. обновление CO сначала доставляет файлы, необходимые для выполнения изменений схемы, а затем пользовательский класс обновления выполняет фактическую модификацию базы данных. Это проблема при переходе более чем на 1 версию, поскольку в этом примере сценарий изменения базы данных с версии 16 на версию 17 никогда не будет применен.

Наш первый подход заключался в гирляндной цепочке папок обновления CO. То есть обновления v.16 с 1.17, обновления 1.17 с 1.18, но это похоже не решает проблему.

Любые идеи?


person sreddy    schedule 23.02.2012    source источник


Ответы (2)


У меня есть надежное приложение ClickOnce, которое также использует SQL Server Express на ПК конечного пользователя. В нашем случае синхронизация схемы локальной базы данных управляется на нашем веб-сервере.

После запуска приложения информация о версии извлекается из текущей клиентской базы данных (при этом возвращается версия «0», если база данных не существует), а затем веб-служба возвращает необходимые файлы сценариев для создания локальной базы данных. Затем приложение ClickOnce выполняет сценарии в последовательном порядке, и схема базы данных строится безупречно, независимо от того, когда пользователь в последний раз запускал приложение.

После обновления локальной схемы любые данные, к которым пользователь должен получить доступ, повторно синхронизируются с сервера. Это связано с тем, что каждый раз, когда я обновляю таблицу данных, мне приходится УДАЛИТЬ таблицу, а затем воссоздавать их из моих сценариев обновления схемы.

Если вы предпочитаете не управлять такой сложной системой управления сервером/клиентским сценарием/базой данных, почему вы не можете связать связанные сценарии SQL со своим приложением? Вы можете сделать это, определив таблицу в вашей клиентской БД, которая поддерживает текущую версию БД. Когда ваш пользователь загружает новое обновление для вашего приложения, проверьте версию БД и, в зависимости от текущей версии БД клиента, выполните доступные сценарии или команды, которые вы скомпилировали с вашим приложением.

Добавляйте скрипты только в каждую последующую публикацию вашего приложения и никогда не удаляйте старые. Новые сценарии SQL должны DROP и воссоздавать любой обновляемый объект. Это может избавить вас от головной боли, если ваше приложение выйдет из строя в середине сценария, выполняемого вашим приложением. Я усвоил это на собственном горьком опыте.

Я бы порекомендовал создать механизм синхронизации, при котором проверка версий управляется с вашего сервера, вместо того, чтобы иметь сценарии или встроенные команды SQL, скомпилированные с вашим приложением. Таким образом, можно вносить незначительные изменения в базу данных без публикации приложения. Поверьте мне, ваши пользователи будут вам благодарны, потому что им не придется часто загружать обновления приложений. Вместо этого эти типы изменений будут плавными и будут происходить автоматически за кулисами.

person RLH    schedule 23.02.2012

Я вставляю метод, который использую для поиска версии программы, если она запускается с рабочего стола, и версии обновления, если она запускается из ClickOnce.

    private string GetTheVersion()
    {
        string version = string.Empty;
        Version currentVersion;
        Version updateVersion;
        StringBuilder sb = new StringBuilder();
        if (ApplicationDeployment.IsNetworkDeployed)
        {
                currentVersion = ApplicationDeployment.CurrentDeployment.CurrentVersion;
            updateVersion = ApplicationDeployment.CurrentDeployment.UpdatedVersion;

            sb.AppendLine(string.Format("Current Version: {0}.{1}.{2}.{3}", currentVersion.Major.ToString(), currentVersion.Minor.ToString(), currentVersion.MajorRevision.ToString(), currentVersion.MinorRevision.ToString()));
            sb.AppendLine(string.Format("Updated Version: {0}.{1}.{2}.{3}", updateVersion.Major.ToString(), updateVersion.Minor.ToString(), updateVersion.MajorRevision.ToString(), updateVersion.MinorRevision.ToString()));
            version = sb.ToString();
        }
        else
        {
            currentVersion = Assembly.GetCallingAssembly().GetName().Version;
            version = string.Format("Current Version: {0}.{1}.{2}.{3}", currentVersion.Major.ToString(), currentVersion.Minor.ToString(), currentVersion.MajorRevision.ToString(), currentVersion.MinorRevision.ToString());
        }

        return version;
    }

Конечно, там больше, чем вам нужно, но затем вы можете использовать методы класса ApplicationDeployment.CurrentDeployment, чтобы определить, следует ли выполнять обновление. Вы можете передать минимальную версию, которую вы хотите, чтобы существующее приложение было в аргументе командной строки или в переменной строки запроса URL, в зависимости от того, как вы развертываете.

Джоуи

person Joseph Morgan    schedule 09.02.2016