Sem categoria

Movendo nenhum esquema para cima da pilha com C# e tipos dinâmicos

Uma das vantagens significativas de trabalhar com o Couchbase Server 2.0 é seu esquema flexível. Os documentos são armazenados como JSON, permitindo registros implicitamente estruturados que não impõem ordem uns aos outros. No mundo real, essa "estrutura implícita" vem do seu aplicativo. Quando você cria um novo usuário no seu aplicativo, o documento associado é uma versão serializada em JSON do seu objeto de domínio.

público classe Usuário
{
    [JsonIgnore]
    público string Id { obter; definir; }
   
    [JsonProperty("nome de usuário")]
    público string Nome de usuário { obter; definir; }
   
    [JsonProperty("senha")]
    público string Senha { obter; definir; }
   
    [JsonProperty("tipo")]
    público Tipo de string { obter { retorno "usuário"; } }
}

//armazenado como { "username" : "hmoody", "password" : "b3cca" }

Embora essa abordagem seja comum em aplicativos em que os documentos são lidos e gravados a partir de objetos de domínio bem definidos, há casos em que a estrutura dos documentos é intencionalmente menos bem definida. Nesses casos, talvez não seja viável ter um objeto de domínio por tipo de documento. 

Embora em linguagens como Python ou Ruby possa ser comum usar uma abordagem menos orientada a objetos (por exemplo, dicionários ou hashes), em linguagens fortemente tipadas, como C# ou Java, é muito mais comum representar os dados do aplicativo usando objetos de dados fortemente tipados, geralmente chamados de objetos simples (Java|C#). Entretanto, certamente é possível usar abordagens de linguagem dinâmica com essas linguagens. 

Quando um usuário perguntou recentemente no StackOverflow Como extrair documentos JSON do Couchbase e transformá-los em objetos C# de tipagem livre, propus duas opções. No restante deste post, descreverei alguns métodos básicos de extensão que você pode usar para adotar uma abordagem semelhante com seus dados.

A primeira abordagem é armazenar Dicionário instâncias. Os dicionários mapeiam naturalmente as estruturas JSON, portanto, são uma opção natural para trabalhar com documentos de forma menos estruturada. Os dicionários aninhados também se adaptam bem a estruturas JSON complexas. 

var user1 = novo Dicionário<string, objeto>
{
    { "nome de usuário", "jzablocki" },
    { "preferências", novo Dicionário<string, objeto>
        {
            { "tema",  "verde"},
            { "timezone",  "EST" }
        }
    }
};

Para salvar e ler esse documento, adicionaremos métodos de extensão para salvar e recuperar dicionários. Esses métodos ficarão dentro de uma nova classe estática chamada CouchbaseDynamicExtensions.

público estático classe CouchbaseDynamicExtensions { }

O primeiro método simplesmente envolverá o método padrão ExecuteStore mas encapsulará algumas coisas. Primeiro, ele cuidará da serialização do Dictionary para JSON usando a biblioteca Newtonsoft.JSON. Você pode modificar as configurações do serializador para dar suporte a camel casing ou outras opções de formatação de JSON. Deixei os padrões no lugar. Em segundo lugar, encapsulei o IStoreOperationResponse em um retorno de tupla indiscutivelmente mais simples. Como as tuplas são comumente retornadas em linguagens dinâmicas, e eu estou tentando ser mais dinâmico, essa pareceu ser uma abordagem apropriada.

público estático Tuple<bool, int, string> StoreDictionary(este Cliente ICouchbaseClient, StoreMode storeMode,
                                            string chave, Dicionário<string, objeto> dicionário)
{
    var json = JsonConvert.SerializeObject(dicionário);
    var result = cliente.ExecuteStore(storeMode, key, json);

    se (!resultado.Sucesso)
    {
        se (resultado.Exceção != nulo) lançar resultado.Exceção;

        retorno Tuple.Criar(falso, resultado.StatusCode.HasValue ? resultado.StatusCode.Valor : 1, resultado.Mensagem);
    }

    retorno Tuple.Criar(verdadeiro, 0, string.Vazio);
}

Obter o Dictionary de volta do JSON armazenado simplesmente inverte o processo. Novamente, estou envolvendo o IGetOperationResult em um Tuple e cuidando da desserialização do JSON armazenado em um Dicionário instância.

público estático Tuple<bool, int, string, Dicionário<string, objeto>> GetDictionary(este Cliente ICouchbaseClient, string chave)
{
    var result = cliente.ExecuteGet<string>(chave);

    se (!resultado.Sucesso)
    {
        se (resultado.Exceção != nulo) lançar resultado.Exceção;

        retorno Tuple.Criar<bool, int, string, Dicionário<string, objeto>>
                    (falso, resultado.StatusCode.HasValue ? resultado.StatusCode.Valor : 1, resultado.Mensagem, nulo);
    }

    var dict = JsonConvert.DeserializeObject<Dicionário<string, objeto>>(resultado.Valor);
    retorno Tuple.Criar(verdadeiro, 0, string.Vazio, dict);
}

O salvamento e a recuperação são simples (não se esqueça de adicionar um using ao namespace da classe de extensão).

var result = cliente.StoreDictionary(StoreMode.Conjunto, "user_1", user1);
se (resultado.Item1)
{
   var dict = cliente.GetDictionary("user_1").Item4;
   Console.WriteLine(ditado); //deve ser o resultado de Dictionary.ToString()
}

Uma abordagem mais interessante seria aproveitar as vantagens do novo dinâmico digitação e o ExpandoObject classe. Esses recursos permitem que os desenvolvedores instruam o compilador a realizar a verificação de tipo em tempo de execução, e não em tempo de compilação. Trabalhar com documentos JSON é um ótimo caso de uso para a dinâmica.

Os métodos de extensão dinâmica são quase idênticos, exceto pelo fato de que antes havia dicionários e agora há tipos dinâmicos. 

público estático Tuple<bool, int, string> StoreDynamic(este Cliente ICouchbaseClient, StoreMode storeMode,
                                            string key, ExpandoObject obj)
{
    var json = JsonConvert.SerializeObject(obj);
    var result = cliente.ExecuteStore(storeMode, key, json);

    se (!resultado.Sucesso)
    {
        se (resultado.Exceção != nulo) lançar resultado.Exceção como Exceção;

        retorno Tuple.Criar(falso, resultado.StatusCode.HasValue ? resultado.StatusCode.Valor : 1, resultado.Mensagem);
    }

    retorno Tuple.Criar(verdadeiro, 0, string.Vazio);
}

público estático Tuple<bool, int, string, ExpandoObject> GetDynamic(este Cliente ICouchbaseClient, string chave)
{
    var result = cliente.ExecuteGet<string>(chave);

    se (!resultado.Sucesso)
    {
        se (resultado.Exceção != nulo) lançar resultado.Exceção;

        retorno Tuple.Criar<bool, int, string, ExpandoObject>
                    (falso, resultado.StatusCode.HasValue ? resultado.StatusCode.Valor : 1, resultado.Mensagem, nulo);
    }

    var obj = JsonConvert.DeserializeObject<ExpandoObject>(resultado.Valor);
    retorno Tuple.Criar(verdadeiro, 0, string.Vazio, obj);
}

Usando instâncias dinâmicas em seu código, você pode salvar e recuperar dados de e para o Couchbase Server. Observe que você também pode ler qualquer documento JSON em um ExpandoObject usando a abordagem de código abaixo. Para testar isso, você pode chamar GetDynamic com uma chave de "user_1".

usuário dinâmico2 = novo ExpandoObject();
usuário2.Nome de usuário = "jzablocki";
usuário2.Preferências = novo ExpandoObject();
usuário2.Preferências.Tema = "verde";
usuário2.Preferências.Fuso horário = "EST";

cliente.StoreDynamic(StoreMode.Conjunto, "user_2", user2 como ExpandoObject);
var getResult = cliente.GetDynamic("user_2");
se (getResult.Item1)
{
    item dinâmico = getResult.Item4;
    Console.WriteLine(item.Preferências.Tema);
}

Há abordagens alternativas para as extensões dinâmicas que exigem a conversão, devido às limitações de chamar um método de extensão com argumentos dinâmicos. Para simplificar as coisas, eu me limitei a ExpandoObject argumentos. 

Obviamente, o C# não é uma linguagem puramente dinâmica e, portanto, alguns dos métodos são menos concisos do que seriam em suas contrapartes puramente late bound. Entretanto, esses métodos demonstram que você não precisa abrir mão de toda a riqueza de um banco de dados orientado a documentos sem esquema só porque sua linguagem é estaticamente tipada, desde que essa linguagem seja C#, é claro...
Compartilhe este artigo
Receba atualizações do blog do Couchbase em sua caixa de entrada
Esse campo é obrigatório.

Autor

Postado por John Zablocki, NET. SDK, Couchbase

John Zablocki é um desenvolvedor NET. SDK Developer na Couchbase. John também é o organizador do Beantown ALT.NET e ex-adjunto da Fairfield University. Você também pode conferir o livro na Amazon chamado "Couchbase Essentials", que explica como instalar e configurar o Couchbase Server.

2 Comentários

  1. Rochester NY movers novembro 27, 2013 em 7:05 am

    Muito bom o post, obrigado por compartilhar...............

  2. Nandkishor Ingavale maio 13, 2015 em 2:26 pm

    John, sua postagem é muito útil.

Deixe um comentário

Pronto para começar a usar o Couchbase Capella?

Iniciar a construção

Confira nosso portal do desenvolvedor para explorar o NoSQL, procurar recursos e começar a usar os tutoriais.

Use o Capella gratuitamente

Comece a trabalhar com o Couchbase em apenas alguns cliques. O Capella DBaaS é a maneira mais fácil e rápida de começar.

Entre em contato

Deseja saber mais sobre as ofertas do Couchbase? Deixe-nos ajudar.