EventoObtenha 50% de desconto no seu ingresso para MongoDB.local Londres em outubro 2. Use o código WEB50Saiba mais >>
Desenvolvedor MongoDB
Central de desenvolvedor do MongoDBchevron-right
Idiomaschevron-right
C#chevron-right

Usando polimorfismo com MongoDB e C#

Markus Wildgruber6 min read • Published Apr 30, 2024 • Updated Apr 30, 2024
C#
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Em comparação com relational database management systems (RDBMS), o esquema flexível do MongoDB é um grande avanço no tratamento de dados orientados a objetos. Essas estruturas geralmente fazem uso de polimorfismo, onde as classes base comuns contêm os campos compartilhados que estão disponíveis para todas as classes na hierarquia; classes derivadas adicionam os campos que são relevantes apenas para os objetos específicos. Um exemplo poderia ser ter vários tipos de veículos, como carros e motocicletas, que possuem alguns campos em comum, mas cada tipo também adiciona alguns campos que só fazem sentido se usados para um tipo:
Um diagrama de classes de entidade mostrando um tipo de veículo e, em seguida, classes de carro e bicicleta que o estendem
Para o RDBMS, armazenar uma hierarquia de objetos é um desafio. Uma maneira é armazenar os dados em uma tabela que contém todos os campos de todas as classes, embora para cada linha seja necessário apenas um subconjunto de campos. Outra abordagem é criar uma tabela para a classe base que contém os campos compartilhados e adicionar uma tabela para cada classe derivada que armazena as colunas do tipo específico e faz referência à tabela base. Nenhuma dessas abordagens é ideal em termos de armazenamento e quando se trata de consultar os dados.
No entanto, com o esquema flexível do MongoDB, pode-se armazenar facilmente documentos na mesma coleção que compartilham apenas alguns, mas não todos os campos. Este artigo mostra como o driverdoMongoDB C# facilita o uso disso para armazenar hierarquias de classes de uma forma muito natural.
Exemplos de casos de uso incluem o armazenamento de metadados para vários tipos de documentos, por exemplo, ofertas, faturas ou outros documentos relacionados a parceiros de negócios em uma collection. Os campos comuns podem ser o título do documento, um resumo, a data, uma incorporação vetorial e a referência ao parceiro de negócios, enquanto uma fatura adicionaria campos para os itens e totais da linha, mas não adicionaria os campos para um relatório de projeto.
Outro caso de uso possível é servir uma visão geral e uma visualização detalhada da mesma collection. Veremos mais de perto como implementar isso no resumo deste artigo.

Noções básicas

Ao acessar uma collection do C#, usamos um objeto que implementa a interfaceIMongoCollection<T> . Este objeto pode ser criado assim:
Ao serializar ou deserializar documentos, o parâmetro de tipo T e o tipo real do objeto fornecem ao driver C# do MongoDB uma dica sobre como mapear a representação BSON para uma classe C# e vice-versa. Se apenas documentos do mesmo tipo residirem na coleção, o driver usará o mapa de classe do tipo.
No entanto, para poder lidar com as hierarquias de classes corretamente, o driver precisa de mais informações. É aqui que entra o discriminador de tipo. Ao armazenar um documento de um tipo derivado na coleção, o driver adiciona um campo chamado _t ao documento que contém o nome da classe, por exemplo:
leva à seguinte estrutura de documento:
Ao desserializar o documento, o valor do campo _t é utilizado para identificar o tipo do objeto que deve ser criado.
Embora isso funcione imediatamente sem configuração específica, é recomendável oferecer suporte ao driver especificando a hierarquia de classes explicitamente usando o atributoBsonKnownTypes, se você estiver usando o mapeamento declarativo:
Se você configurar os mapas de classe imperativamente, basta adicionar um mapa de classe para cada tipo na hierarquia para obter o mesmo efeito.
Por padrão, somente o nome da classe é usado como valor para o discriminador de tipo. especialmente se a hierarquia abranger vários níveis e você desejar executar query de qualquer nível da hierarquia, deverá armazenar a hierarquia como uma array no discriminador de tipo usando o atributoBsonDiscriminator :
Isso aplica uma convenção discriminatória diferente aos documentos e armazena a hierarquia como uma matriz:
Para obter mais detalhes sobre como configurar os mapas de classes para objetos polimórficos, consulte a documentação do driver.

Consultando collection com documentos polimórficos

Ao ler objetos de uma coleção, o driver C# do MongoDB usa o discriminador de tipo para identificar o tipo correspondente e criar um objeto C# da classe correspondente. A seguinte query pode gerar Car Motorcycle objetos e :
Se você estiver interessado apenas em documentos de um tipo específico, poderá criar outra instância de IMongoCollection<T> que retorne apenas estes:
Esta nova instância de coleção respeita o discriminador de tipo correspondente sempre que uma operação é executada. A declaração a seguir remove apenas Car documentos da coleção, mas mantém os documentosMotorcycle como estão:
Se você estiver usando o provedor LINQ oferecido pelo driver C# do MongoDB, também poderá usar o método de extensão LINQ OfType<T> para recuperar somente os objetosCar :

Servindo várias visualizações de uma única coleção

Como esperado antes, agora examinamos mais de perto um caso de uso de polimorfismo: suponha que estamos construindo um sistema que ofereça suporte ao monitoramento de sensores distribuídos em vários locais. O sistema deve fornecer uma visão geral que liste todos os sites com seu nome e o último valor que foi relatado para o site, juntamente com um carimbo de data/hora. Ao selecionar um site, o sistema mostra informações detalhadas do site que consistem em todos os dados da visão geral e também lista os sensores localizados no local específico com seu último valor e sua data e hora.
Isso pode ser representado criando uma classe base para os documentos que contêm o ID do site, um nome para identificar o documento e a última medida, se disponível. Uma classe derivada para a visão geral do site adiciona o endereço do site; outro para os detalhes do sensor contém a localização do sensor:
Ao ingestão de novas medições, tanto a visão geral do site quanto os detalhes do sensor são atualizados (para simplificar, não usamos uma transação de vários documentos):
A amostra acima usa FindAndUpdateAsync para atualizar o documento de detalhes do sensor e também recuperar o documento resultante para que o ID do site possa ser determinado. Se o ID do site for conhecido de anteposição, uma atualização simples também poderá ser usada.
Ao recuperar os documentos para a visão geral do site, o código a seguir retorna todos os documentos relevantes:
Ao exibir dados detalhados de um site específico, a query a seguir recupera todos os documentos do site por seu ID em uma única solicitação:
O resultado da query pode conter objetos de diferentes tipos; você pode usar o método de extensão LINQ OfType<T> na lista para discernir entre os tipos, por exemplo, ao criar um modelo de visualização.
Essa abordagem permite uma consulta eficiente de diferentes perspectivas para que as visualizações centrais do aplicativo possam ser atendidas com carga mínima no servidor.

Resumo

O polimorfismo é uma funcionalidade importante das linguagens orientadas a objetos e há uma ampla variedade de casos de uso para ele. Como você pode ver, o driver C# do MongoDB fornece uma ponte sólida entre a orientação a objetos e o esquema de documentos flexíveis do MongoDB. Se você quiser se afundar no assunto do ponto de vista da modelagem de dados, não deixe de conferir a parte depadrões polimórficos da soberba série "Construindo com padrões" no MongoDB Developer Center.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.
Iniciar a conversa

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Tutorial
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Tutorial

Integrar o Azure Key Vault com a criptografia em nível de campo no lado do cliente do MongoDB


May 24, 2022 | 9 min read
Artigo

Modelagem avançada de dados com o Realm .NET


Oct 19, 2022 | 7 min read
Tutorial

Working With MongoDB Transactions With C# and the .NET Framework


Sep 11, 2024 | 3 min read
Tutorial

Create a RESTful API With .NET Core and MongoDB


Sep 11, 2024 | 8 min read
Sumário