Então, eu tenho um sistema relativamente simples. Um cliente móvel cria registros em um banco de dados sqlite que eu gostaria de ter sincronizado com um servidor SQL remoto (que é compartilhado com outros clientes móveis) . Portanto, quando eu crio um novo registro na tabela sqlite do telefone, eu envio essa alteração para o meu serviço remoto por meio de uma API RESTful. O problema que estou tendo é como solicito as chaves primárias para que não ocorram colisões nos dados (ou seja, um registro no telefone tem a mesma chave primária que um registro completamente diferente no servidor). Qual é a "melhor prática usual" para referenciar o registro no cliente e para referenciar o mesmo registro no servidor?
sql
web-services
JoeCortopassi
fonte
fonte
Respostas:
A prática normal é estruturar seu banco de dados com
uniqueidentifier
chaves (às vezes chamadas de UUIDs ou GUIDs). Você pode criá-los em dois lugares sem medo realista de colisão.Em seguida, seu aplicativo para celular precisa sincronizar tabelas de "fatos" do servidor antes que você possa criar novas linhas. Ao criar novas linhas, faça-o localmente e, quando sincronizar novamente, novas linhas serão adicionadas ao servidor. Você pode fazer o mesmo com atualizações e exclusões também.
Para rastrear inserções, você precisa de um carimbo de data / hora criado nas suas linhas. Para rastrear atualizações, você precisa acompanhar um carimbo de data e hora do LastUpdate em suas linhas. Para rastrear exclusões, você precisa de uma tabela de marca para exclusão.
Observe que, quando você faz uma sincronização, precisa verificar o deslocamento de tempo entre o servidor e o dispositivo móvel e precisa de um método para resolver conflitos. As inserções não são um grande problema (elas não devem entrar em conflito), mas as atualizações podem entrar em conflito e uma exclusão pode entrar em conflito com uma atualização.
Existem estruturas para lidar com esse tipo de coisa, como o Microsoft Sync Framework .
fonte
Aposto que você absolutamente, sem dúvida, não pode ter integridade referencial entre os dois. Especificamente, seus usuários esperam que o aplicativo móvel funcione quando é desconectado?
Existem duas práticas para isso:
Uma é criar registros "provisórios" no cliente e, quando você os sincronizar com o servidor, o sistema central atribuirá o ID. O cliente pode atualizar o registro local para refletir isso.
A outra é que você distribui a criação do ID de uma maneira que (normalmente de forma probabilística) permita que os clientes criem o ID sem colisões.
Para isso, vá para UUIDs - é improvável que a v4 colida.
Caso contrário, considere algo que coloque o ID exclusivo do dispositivo móvel no ID do registro. Portanto, seu ID de registro pode ser
${imei}-${local sequence number}
ou algo assim, onde o IMEI garante exclusividade, e o número de sequência local é apenas um ID sequencial normal do banco de dados.fonte
Além da resposta de Daniel Pittman , uma possibilidade seria o servidor atribuir a cada cliente um ID de cliente exclusivo e fazer dele uma parte da chave primária.
fonte
Eu tenho o mesmo problema com um projeto no qual estou trabalhando, a solução no meu caso foi criar um campo anulável extra nas tabelas locais denominadas remote_id. Ao sincronizar registros do banco de dados local para o remoto, se remote_id for nulo, isso significa que essa linha nunca foi sincronizada e precisa retornar um ID exclusivo que corresponda ao ID da linha remota.
No aplicativo cliente, vinculo tabelas pelo campo _id, remotamente uso o campo de identificação remota para buscar dados, fazer junções, etc.
exemplo localmente:
exemplo remotamente:
Esse cenário, e sem lógica no código, causaria falhas na integridade dos dados, pois a tabela client_type pode não corresponder ao ID real nas tabelas local ou remota; portanto, sempre que um remote_id é gerado, ele retorna um sinal para o aplicativo cliente pedindo para atualizar o campo _id local, isso dispara um gatilho criado anteriormente no sqlite, atualizando as tabelas afetadas. http://www.sqlite.org/lang_createtrigger.html
1- remote_id é gerado no servidor
2- retorna um sinal para o cliente
3- o cliente atualiza seu campo _id e dispara um gatilho que atualiza as tabelas locais que se juntam ao _id local
Claro que também uso um campo last_updated para ajudar nas sincronizações e evitar sincronizações duplicadas.
fonte