locked
Preservando banco de dados na atualização de uma App RRS feed

  • Pergunta

  • Estou desenvolvendo uma app com banco de dados SQL Compact e dados de configuração na Isolated Storage.

    O banco de dados é criado automaticamente e carregado com dados iniciais, caso o banco não exista na inicialização da app.

    Minha preocupação é que os dados do usuário sejam mantidos em futuras atualizações da app. Como esta é a minha primeira app a ser publicada, gostaria de me certificar de fazer algo que não traga problemas de perda de dados aos usuários durante as próximas atualizações.

    Sempre que realizo um novo Deploy no meu Windows Phone, o banco de dados é apagado e criado na inicialização da app, como se fosse a primeira instalação. Existe algum procedimento diferenciado para tratar esta situação ou é uma particularidade do Deploy em desenvolvimento?


    Andrey Kurka

    sábado, 30 de junho de 2012 02:53

Respostas

  • Andrey, as actualizações das aplicações não afectam o Isolated Storage, ou seja, até que a aplicação seja desinstalada (e com isso, o Isolated Storage dessa aplicação é também ele limpo), cabe à aplicação gerir esse espaço.

    Nenhuma actualização irá por si só mexer nos dados em Isolated Storage, tens é que ter o cuidado de manter retro-compatibilidade ou então verificar que tens dados num formato antigo e fazer o upgrade na primeira execução da nova versão da aplicação!


    Pedro Lamas
    DevScope | Senior Software Development Engineer & WP7 Development Speaker
    www.pedrolamas.com | @pedrolamas

    sábado, 30 de junho de 2012 16:46
  • Veja bem Everaldo, as necessidades variam muito de acordo com cada aplicação.

    Se você tem 1000 linhas de consulta e que estas linhas virão junto com a instalação da aplicação, provavelmente eu utilizaria um arquivo XML. Mas, como você está dizendo que quer alterar 300 das 1000 linhas de consulta, então a tabela não será apenas de leitura, sendo assim, eu arriscaria anexar um banco SQL Compact (SDF) no projeto. A leitura e escrita deste banco você faz através do Entity Framework. Caso precise de uma boa referência, assista estes vídeos que me ajudaram muito:

    Entity Framework

    SQL Compact

    O banco de dados do seu cliente deve ficar na Isolated Storage para que não eja atualizado juntamente com as atualizações da sua aplicação, ok? Este banco da Isolated Storage somente será removido junto com a aplicação.

    Espero ter ajudado.

    As respostas que ajudaram no esclarecimento, marque para que outros possam seguir facilmente.

    Abraço e qualquer coisa, continue postando.


    Andrey Kurka


    domingo, 2 de setembro de 2012 03:28

Todas as Respostas

  • Andrey, as actualizações das aplicações não afectam o Isolated Storage, ou seja, até que a aplicação seja desinstalada (e com isso, o Isolated Storage dessa aplicação é também ele limpo), cabe à aplicação gerir esse espaço.

    Nenhuma actualização irá por si só mexer nos dados em Isolated Storage, tens é que ter o cuidado de manter retro-compatibilidade ou então verificar que tens dados num formato antigo e fazer o upgrade na primeira execução da nova versão da aplicação!


    Pedro Lamas
    DevScope | Senior Software Development Engineer & WP7 Development Speaker
    www.pedrolamas.com | @pedrolamas

    sábado, 30 de junho de 2012 16:46
  • Salve Pedro!

    O que seria esta retro-compatibilidade?

    Quanto a estrutura do banco de dados, entendo que se houver alguma mudança, esta atualização deverá ser feita na primeira execução da nova versão. Até aqui, sem problemas.

    Por enquanto, se eu espetar meu Windows Phone via USB e rodar o Deploy, o banco de dados tem sido apagado. É como se a aplicação fosse desinstalada e instalada novamente. Este é o comportamento do Deploy via USB ou estou cometendo algum erro de configuração?


    Andrey Kurka

    domingo, 1 de julho de 2012 16:07
  • Andrey Kurka já solucionou seu problema???

    To com mesmo problema que vc, to pensando em deixar um banco só para consultas na pasta da aplicação, e um no isolated store para a gravação de dados. Já que não consegui quando copio o banco de dados local para a isolated store, uma maneira posterior de atualizar parte dele (atualizar sua estrutura tem como com uma atualização do shema como está aqui http://msdn.microsoft.com/en-us/library/hh394022(v=vs.92).aspx) atualizar apenas parte dos dados (se era isso que vc queria saber), ainda não sei como.

    Pra ver se eu entendi direito vc queria colocar um banco já com dados iniciais, depois os usuários poderiam acrescentar dados nele, e depois com uma atualização, vc atualizasse os dados que vc já tinha na tabela preservando os dados dos usuários. É isso?

    Então, no caso o único jeito que eu ví foi assim tendo dois bancos de dados um para apenas leitura que ficaria na pasta da aplicação, e outro que seria construído na isolated, aí quando vc atualizasse os dados do banco usado apenas para consulta não interferiria no outro. Mas ai já vem uma outra questão que vai ser a velocidade das consultas...

    Ainda tenho mais uma questão que seria de vc fazer pequenas inserções de dados, fazer por código, parecido dos métodos usados para quando o usuário vai inserir dados, mas imagina fazer isso com uma quantidade de dados relativamente grande...

    Enfim o que eu sei ate agora é isso...

    sábado, 1 de setembro de 2012 06:09
  • Opa Everaldo!

    Sim, a dúvida foi esclarecida. Particularmente mantenho sempre meu banco de dados na IsolatedStorage. Olha como ficou a chamada de criação e atualização do banco de dados.

    /// <summary>
            /// Verifica a existência do banco de dados e suas atualizações
            /// </summary>
            private void VerificaBancoInicial()
            {
                using (FingersOnFinanceContext ctx = new FingersOnFinanceContext(sConn))
                {
                    //Verificando existência do banco de dados
                    if (!ctx.DatabaseExists())
                    {
                        ctx.CreateDatabase();
                        
                        // Set the new database version.
                        DatabaseSchemaUpdater dbUpdater = ctx.CreateDatabaseSchemaUpdater();
                        dbUpdater.DatabaseSchemaVersion = App.DB_VERSION;
                        dbUpdater.Execute();
                    }
                    else
                    {
                        DatabaseSchemaUpdater dbUpdater = ctx.CreateDatabaseSchemaUpdater();
                        Int32 DB_versao_atual = dbUpdater.DatabaseSchemaVersion;
    
                        if (DB_versao_atual < App.DB_VERSION)
                        {
                            switch (App.DB_VERSION)
                            {
                                case 1:
                                    //Coluna adicionada para armazenar o identificador do Reminder para o lançamento
                                    dbUpdater.AddColumn<FOFkLancamento>("LctReminder");
                                    break;
    
                                case 2:
                                    break;
                            }
                            
                            
                            //Atualiza versão do banco de dados e aplica alterações
                            dbUpdater.DatabaseSchemaVersion = App.DB_VERSION;
                            dbUpdater.Execute();
                        }
    
                    }
                    
    
                    //Verifica cadastro das Categorias de Despesas
                    var queryCategoria = ctx.FOFkCategoriaDespesas.FirstOrDefault();
    
                    if (queryCategoria == null)
                    {
                        for (int i = 1; i <= 3; i++)
                        {
                            switch (i)
                            {
                                case 1:
                                    var a = new FOFkCategoriaDespesa() { CatDescricao = dicionario.lstCategoriaRecebimentos, CatTipo = "C", CatStatus = 0 };
                                    ctx.FOFkCategoriaDespesas.InsertOnSubmit(a);
                                    break;
                                case 2:
                                    var b = new FOFkCategoriaDespesa() { CatDescricao = dicionario.lstCategoriaDespesasEventuais, CatTipo = "D", CatStatus = 0 };
                                    ctx.FOFkCategoriaDespesas.InsertOnSubmit(b);
                                    break;
                                case 3:
                                    var c = new FOFkCategoriaDespesa() { CatDescricao = dicionario.lstCategoriaRefeicoes, CatTipo = "D", CatStatus = 0 };
                                    ctx.FOFkCategoriaDespesas.InsertOnSubmit(c);
                                    break;
                            }
                        }
                        
                        ctx.SubmitChanges();
                    }
    
                    //Verifica cadastro dos Meios de Pagamento
                    var queryPagamento = ctx.FOFkPagamentoMeios.FirstOrDefault();
    
                    if (queryPagamento == null)
                    {
                        for (int i = 1; i <= 2; i++)
                        {
                            switch (i)
                            {
                                case 1:
                                    var a = new FOFkPagamentoMeio() { PagDescricao = dicionario.lstPagamentoMeioDinheiro, PagStatus = 0 };
                                    ctx.FOFkPagamentoMeios.InsertOnSubmit(a);
                                    break;
                                case 2:
                                    var b = new FOFkPagamentoMeio() { PagDescricao = dicionario.lstPagamentoMeioTEF, PagStatus = 0 };
                                    ctx.FOFkPagamentoMeios.InsertOnSubmit(b);
                                    break;
                            }
                        }
    
                        ctx.SubmitChanges();
                    }
    
    
                }
            }

    Esteja atento para o CreateDatabaseSchemaUpdater e para a versão do banco de dados.

    O App.DB_VERSION foi criado público no App.xaml.cs e quando crio uma nova atualização, atualizo esta constante para fazer a lógica que publiquei neste código acima.

    Fui um pouco mais perfeccionista e usei o switch para manter sempre todas as atualizações realizadas documentadas (para meu controle apenas). Desta maneira eu comparo a versão atual do banco de dados com a versão da App.DB_VERSION. Sempre que a constante for superior à versão corrente, a aplicação vai procurar no switch a atualização correspondente.

    Note que não estou fazendo alterações grandes que exigem migrar dados ou algo semelhante. Neste exemplo estou adicionando um atributo que pode ser nulo para os registros existentes. Mas com estes recursos você poderá fazer qualquer tipo de alteração no banco.

    Espero que tenha ajudado.

    Abraço


    Andrey Kurka

    sábado, 1 de setembro de 2012 17:08
  • Andrey kurka ótimo código!

    Mas me responda uma coisa, no caso de uma banco com duas tabelas uma sendo pra consulta e outra para gravação de dados, como por exemplo tenho 1000 linhas de consulta, e para cada uma dessas linhas de consulta pode haver ou não uma linha gravada pelo usuário. Teria como alterar por exemplo 300 linhas dessa tabela de consulta sem alterar a outra tabela que seria para gravação pelo usuário?
    E como por exemplo como modificar mais de 500 linhas no banco de consulta, não seria melhor ter um banco de consulta que fica na pasta da aplicação e um banco na para gravação na parte isolada. Porque eu pensei no caso na atualização dos dados, serem muitas. Ai também pega a parte da velocidade das consultas sendo dois bancos... para atualizações de dados referências grandes, e feita de forma periódica, o que vc acha???

    Obrigado!
    domingo, 2 de setembro de 2012 00:40
  • Veja bem Everaldo, as necessidades variam muito de acordo com cada aplicação.

    Se você tem 1000 linhas de consulta e que estas linhas virão junto com a instalação da aplicação, provavelmente eu utilizaria um arquivo XML. Mas, como você está dizendo que quer alterar 300 das 1000 linhas de consulta, então a tabela não será apenas de leitura, sendo assim, eu arriscaria anexar um banco SQL Compact (SDF) no projeto. A leitura e escrita deste banco você faz através do Entity Framework. Caso precise de uma boa referência, assista estes vídeos que me ajudaram muito:

    Entity Framework

    SQL Compact

    O banco de dados do seu cliente deve ficar na Isolated Storage para que não eja atualizado juntamente com as atualizações da sua aplicação, ok? Este banco da Isolated Storage somente será removido junto com a aplicação.

    Espero ter ajudado.

    As respostas que ajudaram no esclarecimento, marque para que outros possam seguir facilmente.

    Abraço e qualquer coisa, continue postando.


    Andrey Kurka


    domingo, 2 de setembro de 2012 03:28
  • Isso mesmo que eu tava achando, muito obrigado pela resposta e ajudou muito!
    domingo, 2 de setembro de 2012 03:54