Menu Docs
Página inicial do Docs
/ /
Atlas Device SDKs
/ /

Gerenciar assinaturas de Flexible Sync- .NET SDK

Nesta página

  • Gerenciar suas assinaturas
  • Adicionar uma assinatura
  • Bootstrap the Realm com assinaturas iniciais
  • Adicionar uma assinatura ao conjunto de assinaturas existente
  • Várias assinaturas em lote
  • Opções de assinatura
  • Atualizar assinaturas com uma nova query
  • Remover subscrições
  • Remover uma assinatura por query
  • Remover uma assinatura por nome
  • Remover todas as assinaturas de um nome de classe ou tipo de objeto
  • Remover todas as assinaturas
  • Aguarde as alterações na assinatura para sincronizar
  • Estado da assinatura
  • Requisitos e limitações do Flexible Sync RQL
  • Requisitos de inscrição de campos de query indexados
  • Operadores de consulta não suportados na sincronização flexível
  • Listar queries
  • Objetos incorporados ou vinculados
  • Limite de tamanho da query

Flexible Sync usa assinaturas e permissões para determinar quais dados sincronizar com seu aplicativo.

Para usar o Flexible Sync em um aplicativo .NET:

  • Configure o Flexible Sync no backend.

  • Inicialize o aplicativo

  • Autenticar um usuário em seu projeto de cliente.

  • Abra o Realm sincronizado com uma configuração Flexible Sync

  • Adicione assinaturas ao aplicativo cliente

Você pode adicionar, atualizar e remover assinaturas de query para determinar quais dados são sincronizados com o dispositivo cliente.

Observação

Pré-requisitos do Flexible Sync

Para ativar o Flexible Sync em seu aplicativo, é necessário um cluster de Atlas não fragmentado que execute o MongoDB 5.0 ou superior

Observação

Requisitos de versão do Realm .NET SDK

Além dos requisitos acima, você deve usar o Realm .NET versão 10.9.0 ou superior para usar o Flexible Sync em seu aplicativo cliente .NET.

Importante

Flexible Sync não é compatível com todos os operadores disponíveis no RQL. Consulte LimitaçõesFlexible Sync RQL de sincronização para obter detalhes.

Ao configurar o Flexible Sync no backend, você especifica quais campos seu aplicativo cliente pode executar uma query. No aplicativo cliente, use a API de assinaturas para gerenciar um conjunto de assinaturas para queries específicas em campos consultáveis.

Você pode:

  • Obter uma lista de todas as assinaturas

  • Adicionar subscrições

  • Verificar estado da assinatura

  • Atualizar uma assinatura com uma nova query

  • Remover assinaturas individuais ou todas as assinaturas de um tipo

Quando os dados correspondem à assinatura e o usuário autenticado tem as permissões apropriadas, o Atlas App Services sincroniza os dados de backend com o aplicativo cliente.

Você pode especificar um nome de string para sua assinatura. Se você não der um nome à sua assinatura, o nome será definido como nulo.

Quando você cria uma assinatura, o App Services procura dados correspondentes a uma query em um Tipo de objeto de Realm específico. Em suas assinaturas do Flexible Sync, você pode ter assinaturas em vários Tipo de objeto de Realm diferentes ou várias query no mesmo Tipo de objeto de Realm.

Você não pode criar assinaturas para objetos assimétricos porque eles só enviam dados para o backend do App Services.

Alterado na versão 11.6.1: Dados geoespaciais suportados no Atlas Device Sync

No Realm .NET versão 11,6,1 e posterior, você pode criar assinaturas para queries geoespaciais. Se você tentar se inscrever em uma query geoespacial com uma versão mais antiga do SDK, receberá um erro de servidor com uma gravação compensatória.

Para mais informações, consulte query de Dados Geoespaciais.

Você deve ter pelo menos uma assinatura antes de ler ou escrever no Realm. Você deve criar uma ou mais assinaturas iniciais ao configurar o Flexible Sync, em vez de adicionar assinaturas após a inicialização.

Você pode inicializar um realm com uma assinatura inicial definida ao abri-lo com um FlexibleSyncConfiguration. Defina o parâmetro PopulateInitialSubscriptions como um retorno de chamada que é invocado quando o domínio é criado. Adicione as queries que você deseja usar para inicializar o realm, conforme mostrado no exemplo a seguir:

var config = new FlexibleSyncConfiguration(app.CurrentUser)
{
PopulateInitialSubscriptions = (realm) =>
{
var myItems = realm.All<Item>().Where(n => n.OwnerId == myUserId);
realm.Subscriptions.Add(myItems);
}
};
// The process will complete when all the user's items have been downloaded.
var realm = await Realm.GetInstanceAsync(config);

Você deve inicializar um domínio com seu SubscriptionSet. Em seguida, você pode acessar o conjunto de assinaturas com a propriedade Realm.Subscriptions se precisar adicionar queries adicionais ou atualizar assinaturas existentes.

Para adicionar uma assinatura a um conjunto de assinaturas existente, crie a query e chame IQueryable.SubscribeAsync():

var query = realm.All<Team>().Where(t => t.Name == "MyTeam");
await query.SubscribeAsync();
// you can also pass a SubscriptionOptions object:
var query2 = realm.All<Team>().Where(t => t.Name == "DevelopmentTeam");
await query2.SubscribeAsync(
new SubscriptionOptions() { Name = "devTeamSubscription" });

O método SubscribeAsync é uma abreviatura para utilizar SubscriptionSet.Update() para criar um bloco de atualização e, em seguida, chamar o método SubscriptionSet.Add() no SubscriptionSet.

Embora você possa adicionar uma única query usando SubscribeAsync, você só pode adicionar várias queries em lote dentro de um bloco SubscriptionSet.Update . Executar atualizações de query é uma operação cara no servidor. É altamente recomendável projetar seu aplicativo para minimizar as atualizações. Você pode fazer isso criando todas as assinaturas em um único bloco de atualização na primeira vez que o usuário iniciar o aplicativo e agrupando em lote quaisquer alterações de acompanhamento no conjunto de assinaturas.

No exemplo abaixo, assinamos três query.

realm.Subscriptions.Update(() =>
{
// Subscribe to all long running items, and name
// the subscription "longRunningItems"
var longRunningTasksQuery = realm.All<Item>()
.Where(t => t.ProgressMinutes > 120);
realm.Subscriptions.Add(longRunningTasksQuery,
new SubscriptionOptions() { Name = "longRunningItems" });
// Subscribe to all of Ben's Items
realm.Subscriptions.Add(realm.All<Item>()
.Where(t => t.Owner == "Ben"));
// Subscribe to all Teams, name the subscription
// 'teamsSubscription', and throw an error if
// this subscription name already exists.
realm.Subscriptions.Add(realm.All<Team>(),
new SubscriptionOptions()
{ Name = "teams", UpdateExisting = false });
});

Observe que ambos os métodos para adicionar uma assinatura fornecem uma sobrecarga para passar um objeto SubscriptionOptions . SubscriptionOptions contém opções de configuração para sua inscrição:

  • um campo de string Name

  • um campo booleano UpdateExisting .

Se UpdateExisting for verdadeiro, adicionar uma assinatura com um nome existente substituirá a query existente pela nova query. Este é o comportamento padrão. No entanto, se você definir UpdateExisting como falso e tentar substituir uma assinatura nomeada por uma query diferente, o Realm lançará uma exceção.

O Realm sempre ignora assinaturas duplicadas, com ou sem nome.

Importante

Assine objetos vinculados

Você deve adicionar um objeto e seu objeto vinculado ao conjunto de assinaturas para ver um objeto vinculado.

Se os resultados de sua assinatura contiverem um objeto com uma propriedade vinculada a um objeto não contido nos resultados, o link parecerá nulo. Não há como distinguir se o valor dessa propriedade é legitimamente nulo ou se o objeto ao qual ela está vinculada existe, mas está fora da visão da assinatura da query.

Você pode atualizar uma assinatura nomeada com uma nova query. Para atualizar a query de uma assinatura, passe a nova query e uma opção de assinatura com o nome da assinatura que você deseja atualizar para o método SubscriptionSet.Add() . Como adicionar uma nova assinatura, você deve atualizar uma assinatura dentro de um bloco de atualização chamando o método SubscriptionSet.Update() .

Observação

Não é possível atualizar uma assinatura sem nome. Como alternativa, você pode excluir a assinatura sem nome e criar uma nova assinatura com a query desejada.

No exemplo a seguir, tarefas de longa duração são redefinidas como quaisquer tarefas que levaram mais de 130 minutos:

realm.Subscriptions.Update(() =>
{
var updatedLongRunningTasksQuery = realm.All<Item>()
.Where(t => t.Status == "completed" && t.ProgressMinutes > 130);
realm.Subscriptions.Add(updatedLongRunningTasksQuery,
new SubscriptionOptions() { Name = "longRunningTasks" });
});

Observação

A tentativa de atualizar uma assinatura que tenha o campo SubscriptionOptions.UpdateExisting definido como falso gerará uma exceção.

Para remover assinaturas do conjunto de assinaturas, você pode:

  • Remover uma única assinatura com a query fornecida

  • Remover uma única assinatura com o nome fornecido

  • Remover uma única assinatura com a assinatura fornecida

  • Remover todas as assinaturas de um tipo específico

  • Remover todas as assinaturas

Quando você remove uma query de assinatura, o servidor também remove os dados sincronizados do dispositivo cliente.

Dentro de um bloco de atualização, você pode remover uma assinatura específica por query. Passe a query para o método Remove() no SubscriptionSet.

No exemplo a seguir, a assinatura de tarefas com um proprietário chamado 'Ben' é removida do conjunto de assinaturas.

realm.Subscriptions.Update(() =>
{
// remove a subscription by it's query
var query = realm.All<Item>().Where(i => i.Owner == "Ben");
realm.Subscriptions.Remove(query);
});

Dentro de um bloco de atualização, você pode remover uma assinatura específica por nome. Passe o nome para o método Remove() no SubscriptionSet.

realm.Subscriptions.Update(() =>
{
// remove a named subscription
var subscriptionName = "longRunningItemsSubscription";
realm.Subscriptions.Remove(subscriptionName);
});

Em um bloco de atualização, você pode remover todas as assinaturas sem nome de uma classe passando o nome da classe como uma string para o método RemoveAll("ClassName") . O método RemoveAll() tem um segundo argumento opcional que é booleano, removedName, que também remove as assinaturas nomeadas se estiver definido como true. removedName é definido como falso por padrão.

Como alternativa, você pode remover todas as assinaturas sem nome de um tipo de objeto com RemoveAll(). O método RemoveAll<Type>() tem um argumento booleano opcional removedName que também remove as assinaturas nomeadas se estiver definido como true. O argumento removedName é definido como falso por padrão.

realm.Subscriptions.Update(() =>
{
// remove all subscriptions of the "Team" Class Name
realm.Subscriptions.RemoveAll("Team");
// Alernatively, remove all subscriptions of the "Team" object type
realm.Subscriptions.RemoveAll<Team>();
});

Dentro de um bloco de atualização, você pode remover todas as assinaturas sem nome do conjunto de assinaturas. Ligue para o método RemoveAll() no SubscriptionSet. O método RemoveAll() tem um argumento booleano opcional removedName que também remove as assinaturas nomeadas se estiver definido como true. removedName é definido como falso por padrão.

realm.Subscriptions.Update(() =>
{
// remove all subscriptions, including named subscriptions
realm.Subscriptions.RemoveAll(true);
});

Mutar o conjunto de assinaturas em um bloco de atualização é apenas uma parte da alteração de uma assinatura. Após a alteração da assinatura local, o Realm sincroniza com o servidor para resolver quaisquer atualizações nos dados devido à alteração da assinatura. Isso pode média adicionar ou remover dados do Realm sincronizado.

Use o método SubscriptionSet.WaitForSynchronizationAsync() para aguardar que o servidor reconheça este conjunto de assinaturas. Se o servidor rejeitar a alteração, o SubscriptionSetState será um estado de erro e uma exceção será lançada.

Uma exceção pode ocorrer se:

  • Uma query não suportada está inscrita. A assinatura de uma query não suportada pausará a sincronização. Para retomar a sincronização, remova a query não suportada.

  • Você está executando uma ação inválida, como adicionar um objeto que não corresponde a uma assinatura. Este Atlas Triggers um reinício do cliente: os dados são apagados do domínio e uma nova cópia dos dados é criada sem nenhuma assinatura no conjunto.

try
{
await realm.Subscriptions.WaitForSynchronizationAsync();
}
catch (SubscriptionException ex)
{
// do something in response to the exception or log it
Console.WriteLine($@"The subscription set's state is Error and synchronization is paused: {ex.Message}");
}

Use a propriedade SubscriptionSet.state para ler o estado atual do conjunto de assinaturas.

O estado Superseded é um SubscriptionSetState que pode ocorrer quando outro tópico atualiza uma assinatura em uma instância diferente do conjunto de assinatura. Se o estado se tornar Superseded, você deverá obter uma nova instância do conjunto de assinaturas antes de poder atualizá-lo.

Observação

Estado da assinatura "Concluído"

O estado do conjunto de assinaturas "complete" não significa que a sincronização "está concluída" ou "todos os documentos foram sincronizados". "Completo" significa que as duas coisas a seguir aconteceram:

  • A assinatura se tornou o conjunto de assinaturas ativo que está sendo atualmente sincronizado com o servidor.

  • Os documentos que correspondiam à assinatura no momento em que a assinatura foi enviada ao servidor agora estão no dispositivo local. Observe que isso não inclui necessariamente todos os documentos que atualmente correspondem à assinatura.

O SDK do Realm não fornece uma maneira de verificar se todos os documentos que correspondem a uma assinatura foram sincronizados com o dispositivo.

Adicionar um campo de query indexado à sua aplicação pode melhorar o desempenho de queries simples em dados fortemente particionados. Por exemplo, uma aplicação onde as queries mapeiam fortemente os dados para um dispositivo, armazém ou usuário, como user_id == $0, “641374b03725038381d2e1fb”, é uma boa candidata para um campo de query indexado. No entanto, um campo de query indexado tem requisitos específicos para uso em uma inscrição de query:

  • O campo de query indexado deve ser usado em todas as inscrições de query. Não pode estar faltando na query.

  • O campo de query indexado deve usar uma comparação == ou IN com uma constante pelo menos uma vez na query de inscrição. Por exemplo, user_id == $0, "641374b03725038381d2e1fb" ou store_id IN $0, {1,2,3}.

Opcionalmente, você pode incluir uma comparação AND, desde que o campo consultável indexado seja comparado diretamente com uma constante usando == ou IN pelo menos uma vez. Por exemplo, store_id IN {1,2,3} AND region=="Northeast" ou store_id == 1 AND (active_promotions < 5 OR num_employees < 10).

As consultas inválidas do Flexible Sync em um campo indexado que pode ser consultado incluem consultas em que:

  • O campo de consulta indexado não utiliza AND com o resto da consulta. Por exemplo store_id IN {1,2,3} OR region=="Northeast" é inválido porque usa OR em vez de AND. Da mesma forma, store_id == 1 AND active_promotions < 5 OR num_employees < 10 é inválido porque o AND só se aplica ao termo ao lado, não à consulta inteira.

  • O campo de consulta indexado não é utilizado em um operador de igualdade. Por exemplo store_id > 2 AND region=="Northeast" é inválido porque utiliza apenas o operador > com o campo de consulta indexado e não tem uma comparação de igualdade.

  • A query está totalmente ausente do campo de query indexado. Por exemplo, region=="Northeast ou truepredicate são inválidos porque não contêm o campo de query indexado.

A Flexible Sync tem algumas limitações ao usar operadores RQL. Quando você escreve a assinatura de consulta que determina quais dados sincronizar, o servidor não oferece suporte a esses operadores de consulta. No entanto, você ainda pode usar toda a gama de recursos de RQL para consultar o conjunto de dados sincronizado no aplicativo cliente.

Tipo de operador
Operadores não suportados
Operadores agregados
@avg, @count, @max, @min, @sum
Sufixos de query
DISTINCT, SORT , LIMIT

Queries que não diferenciam maiúsculas de minúsculas ([c]) não podem usar índices de forma eficaz. Sendo assim, queries que não diferenciam maiúsculas de minúsculas não são recomendadas, pois podem causar problemas de desempenho.

A sincronização flexível suporta apenas @count para campos de array.

A sincronização flexível oferece suporte às listas de query usando o operador IN .

Você pode consultar uma lista de constantes para ver se ela contém o valor de um campo de consulta:

// Query a constant list for a queryable field value
"priority IN { 1, 2, 3 }"

Se um campo de query tiver um valor de array, você poderá consultar para ver se ele contém um valor constante:

// Query an array-valued queryable field for a constant value
"'comedy' IN genres"

Aviso

Não é possível comparar duas listas entre si em uma consulta de sincronização flexível. Observe que esta é uma sintaxe válida do Realm Query Language fora das consultas do Flexible Sync.

// Invalid Flexible Sync query. Do not do this!
"{'comedy', 'horror', 'suspense'} IN genres"
// Another invalid Flexible Sync query. Do not do this!
"ANY {'comedy', 'horror', 'suspense'} != ANY genres"

A sincronização Flexível não oferece suporte à consulta de propriedades em objetos ou links embarcados. Por exemplo, obj1.field == "foo".

O limite de tamanho para qualquer assinatura de query em seu conjunto de assinaturas é de 256 kB. Exceder esse limite resulta em um erro de LimitsExceeded.

Voltar

Gravar em um Realm sincronizado - .NET SDK

Próximo

Lidar com erros de sincronização e tempos limite