POCOs
Nesta página
- Visão geral
- Crie um POCO
- Serialização personalizada
- Serialize propriedades somente para leitura
- Defina nomes de campo
- Selecione o tipo de representação
- Defina a ordem dos campos
- Identifique a propriedade
Id
- Omita campos vazios
- Personalize valores padrão
- Especifique um gerador de ID
- Personalize a serialização de DateTime
- Personalize a serialização do dicionário
- Exemplo
- Informações adicionais
- Documentação da API
Visão geral
Neste guia, você aprenderá como usar "Plain Old CLR/Class Objects", ou POCOs, com o driver .NET/C# para suas operações e consultas. POCOs são objetos de classe simples que não herdam recursos de nenhuma classe base ou interface específica de framework. Recomendamos usar POCOs em seu código C# para aderir ao uso idiomático do driver e obter o melhor desempenho.
Leia este guia para saber mais sobre como usar POCOs com o driver .NET/C#, ou se precisar ajustar o comportamento de mapeamento de campo padrão do driver.
Crie um POCO
Você pode criar um POCO definindo uma classe simples que não implemente interfaces ou estenda classes de um framework. Ao executar uma operação como uma leitura ou gravação utilizando um POCO, o driver internamente serializa ou converte o POCO para BSON.
Selecione a aba POCO ou BSON para ver como o driver serializa uma amostra de POCO para BSON:
public class Clothing { public ObjectId Id { get; set; } public string Name { get; set; } public bool InStock { get; set; } public double Price { get; set; } public List<string> ColorSelection { get; set; } }
{ "_id": ObjectId("..."), "Name": "Long Sleeve Shirt", "InStock": true, "Price": 17.99, "ColorSelection": [ "black", "navy", "red" ] }
Você pode definir um POCO com qualquer estrutura de objeto que atenda às suas necessidades, incluindo objetos aninhados, arrays, listas e quaisquer tipos de dados.
Serialização personalizada
Se o comportamento de mapeamento de campo padrão não atender às suas necessidades, você poderá especificar o comportamento personalizado utilizando atributos relacionados à serialização. Esses atributos alteram a maneira como o driver serializa cada propriedade do seu POCO. Esta seção descreve alguns dos atributos comuns relacionados à serialização.
Serialize propriedades somente para leitura
Se uma propriedade for somente para leitura, o automatizador não a incluirá no mapa de classes para a serialização. Para forçar o automapper a incluir uma propriedade no mapa de classe, aplique o atributo [BsonElement]
na propriedade.
O exemplo de código abaixo aplica o atributo [BsonElement]
à propriedade Upc
da classe Clothing
. Upc
é uma propriedade somente para leitura, pois tem um método get
mas nenhum método set
.
public class Clothing { public ObjectId Id { get; set; } public string Name { get; set; } public bool InStock { get; set; } public double Price { get; set; } public List<string> ColorSelection { get; set; } [ ] public int Upc { get; } }
Você também pode adicionar uma propriedade somente para leitura ao registrar o mapa de classe, conforme mostrado no exemplo abaixo:
BsonClassMap.RegisterClassMap<Clothing>(classMap => { classMap.AutoMap(); classMap.MapProperty(c => c.Upc); });
Observação
Quando o driver .NET/C# serializa uma propriedade somente para leitura, a propriedade e seu valor são armazenados no banco de dados, mas nunca são desserializados novamente.
Defina nomes de campo
O driver serializa propriedades POCO para campos BSON com o mesmo nome de campo e capitalização. Para armazenar uma propriedade com outro nome, use o atributo [BsonElement()]
. O código abaixo mapeia a propriedade YearBuilt
da classe House
para o campo year_built
no documento BSON serializado:
public class House { public Guid Id { get; set; } [ ] public int YearBuilt { get; set; } }
Embora seja comum usar a convenção de nomenclatura Pascal case ao definir classes C#, usar o atributo [BsonElement()]
permite selecionar uma convenção de nome diferente ou personalizada em sua coleção do MongoDB.
Dica
Definir convenção de nomenclatura de campo personalizado
Para serializar cada propriedade com um nome de campo personalizado, você pode definir um ConventionPack
em vez de usar o atributo [BsonElement()]
. Por exemplo, ao definir a classe usando a convenção de nomenclatura Pascal case, você poderá usar o código abaixo para optar por nomes de campo de Camel case no documento serializado:
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() }; ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
Selecione o tipo de representação
Para serializar uma propriedade C# para um tipo de JSON específico, utilize o atributo [BsonRepresentation()]
. Isso funciona somente se o tipo primitivo C# puder ser convertido para o tipo BSON especificado. Na amostra de código abaixo, a propriedade YearBuilt
, definida como um char
em C#, é serializada como um tipo BSON Int32
:
public class House { public Guid Id { get; set; } [ ] public char YearBuilt { get; set; } }
Para obter mais informações sobre conversões de tipo válidas, consulte a Especificação de conversões C#.
Defina a ordem dos campos
O driver serializa propriedades para campos BSON na ordem em que são especificados no POCO. Para armazenar propriedades em uma ordem personalizada para corresponder a um esquema existente, você pode especificar o parâmetro nomeado Order
no atributo [BsonElement()]
. No exemplo de código abaixo, o driver armazena a propriedade YearBuilt
após a propriedade Style
:
public class House { public Guid Id { get; set; } [ ] public int YearBuilt { get; set; } [ ] public string Style { get; set; } }
Se alguma propriedade não tiver um Order
explícito, o driver as serializará na ordem padrão depois de encontrar as que tiverem.
Identificar a propriedade Id
Por padrão, o driver mapeia qualquer propriedade pública denominada Id
, id
ou _id
para o campo BSON _id
. Para selecionar explicitamente a propriedade a ser mapeada para o campo _id
, use o atributo [BsonId()]
. O exemplo de código abaixo mapeia a propriedade Identifier
para o campo _id
:
public class House { [ ] public string Identifier { get; set; } }
Aviso
Vários campos de Id
Se você identificar mais de uma propriedade como o campo _id
usando o atributo [BsonId()]
, o driver lançará um DuplicateBsonMemberMapAttributeException
. Se você especificar o mesmo campo de banco de dados mais de uma vez (por exemplo, se o POCO incluir propriedades denominadas Id
e _id
), o driver lançará um BsonSerializationException
.
Omita campos vazios
Por padrão, o driver serializa propriedades indefinidas para campos com valores null
. Para ignorar propriedades indefinidas durante a serialização, use o atributo [BsonIgnore]
. O código abaixo mostra como evitar que o driver serialize a propriedade YearBuilt
se ela for indefinida:
public class House { public Guid Id { get; set; } [ ] public int YearBuilt { get; set; } public string Style { get; set; } }
Personalize valores padrão
Em C#, uma propriedade possui um valor padrão até você atribuir um valor a ela. O valor padrão depende do tipo de dados da propriedade. Por exemplo, o valor padrão para uma propriedade de tipo de referência é null
.
Para especificar outro valor padrão para uma propriedade, aplique o atributo [BsonDefaultValue()]
na propriedade e passe o valor padrão desejado como um argumento.
Os exemplos de código abaixo aplicam o atributo [BsonDefaultValue()]
à propriedade YearBuilt
. Até que essa propriedade receba um valor, seu valor será 1900
.
public class House { public Guid Id { get; set; } [ ] public int YearBuilt { get; set; } }
Você também pode especificar outro valor padrão para uma propriedade ao registrar o mapa de classe, conforme o exemplo abaixo:
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMap.MapMember(h => h.YearBuilt).SetDefaultValue(1900); });
Por padrão, o Driver .NET/C# serializa todas as propriedades, incluindo aquelas que contêm valores padrão. Para instruir o driver a ignorar uma propriedade que tenha o valor padrão, utilize o atributo [BsonIgnoreIfDefault]
.
O exemplo de código abaixo aplica o atributo [BsonIgnoreIfDefault]
na propriedade YearBuilt
. Se o valor desta propriedade for o padrão para seu tipo de dados (0
para propriedades do int
), o driver não fará a serialização.
public class House { public Guid Id { get; set; } [ ] public int YearBuilt { get; set; } }
Você também pode instruir o driver a ignorar uma propriedade que contém o valor padrão ao registrar o mapa de classe, conforme o exemplo abaixo:
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMap.MapMember(h => h.YearBuilt).SetIgnoreIfDefault(true); });
Ambos podem especificar outro valor predefinido para uma propriedade e instruir o driver a ignorar a propriedade se contiver este valor predefinido. Para tal, aplique os atributos [BsonDefaultValue()]
e [BsonIgnoreIfDefault]
à propriedade, conforme o exemplo de código abaixo:
public class House { public Guid Id { get; set; } [ ] [ ] public int YearBuilt { get; set; } }
O exemplo de código anterior define o seguinte comportamento de serialização:
Se um valor não tiver sido atribuído à propriedade
YearBuilt
, ele terá um valor padrão especificado de1900
.Uma vez que
1900
é o valor predefinido para esta propriedade, o driver irá ignorar a propriedade se tiver este valor.
Especifique um gerador de ID
Cada documento em uma coleção do MongoDB deve ter um ID exclusivo. Ao serializar um objeto em uma coleção, se a propriedade Id
contiver o valor padrão para seu tipo de dados, o driver .NET/C# não fará a serialização. Em vez disso, o driver gera um valor de ID único para a propriedade.
Se a propriedade Id
for do tipo Guid
, ObjectId
ou string
, o driver poderá gerar o valor do ID por conta própria. Se a propriedade Id
for qualquer outro tipo de dados, você deverá especificar o tipo IIdGenerator
que o driver usa para gerar o valor. Para especificar o tipo IIdGenerator
, aplique o atributo [BsonId(IdGenerator)]
à propriedade e passe o tipo IIdGenerator
como argumento.
O driver .NET/C# inclui os seguintes tipos de IIdGenerator
:
Id Tipo de dados de campo | IIdGenerator Tipo |
---|---|
Guid valor gerado pelo algoritmo COMB | CombGuidGenerator |
BsonObjectId | BsonObjectIdGenerator |
No exemplo de código abaixo, se a propriedade Id
da classe House
contiver o valor padrão (null
), o driver utilizará o algoritmo COMB para gerar um valor único durante a serialização:
public class House { [ ] public Guid Id { get; set; } }
Observação
No exemplo de código anterior, se a propriedade Id
não tivesse o atributo [BsonId(IdGenerator)]
, o driver geraria um GUID não COMB para atribuir ao campo Id
.
Você também pode especificar um tipo de IIdGenerator
ao registrar o mapa de classe, conforme o exemplo abaixo:
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMap.MapIdMember(h => h.Id).SetIdGenerator(CombGuidGenerator.Instance); });
Dica
Especifique um IIdGenerator para várias classes
Você pode usar o método RegisterIdGenerator()
para especificar um único IIdGenerator
para todas as propriedades do Id
de um determinado tipo de dados. O exemplo de código abaixo instrui o driver a usar o tipo CombGuidGenerator
para todos os IDs Guid
:
BsonSerializer.RegisterIdGenerator( typeof(Guid), CombGuidGenerator.Instance );
O driver .NET/C# também inclui tipos de IIdGenerator
que validam a propriedade Id
e lançam uma exceção se o ID for inválido. A tabela a seguir lista estes tipos:
Validação de ID | IIdGenerator Tipo |
---|---|
Não é nulo | NullIdChecker |
Nem todos zeros | ZeroIdChecker<T> |
No exemplo de código abaixo, se a propriedade Id
da classe House
contiver o valor padrão (null
), o driver lançará uma exceção:
public class House { [ ] public Guid Id { get; set; } }
Personalize a serialização de DateTime
Para personalizar como o Driver .NET/C# serializa as propriedades do DateTime
, utilize o atributo [BsonDateTimeOptions()]
e especifique a configuração desejada como um argumento.
Se uma propriedade DateTime
representar somente uma data, você poderá aplicar o atributo [BsonDateTimeOptions(DateOnly = true)]
. Se você fizer isso, o driver não executará nenhuma conversão de fuso horário no valor.
No exemplo de código abaixo, a classe PatientRecord
usa um DateTime
para a propriedade DateOfBirth
. O atributo [BsonDateTimeOptions(DateOnly = true)]
indica que a propriedade contém apenas uma data.
public class PatientRecord { public Guid Id { get; set; } [ ] public DateTime DateOfBirth { get; set; } }
Você também pode usar o atributo [BsonDateTimeOptions()]
para especificar o DateTimeKind
de uma propriedade DateTime
. No exemplo de código abaixo, a classe PatientRecord
tem uma propriedade AppointmentTime
do tipo DateTime
. O atributo [BsonDateTimeOptions(Kind = DateTimeKind.Local)]
indica que o componente de tempo do valor da propriedade está na hora local. Quando o driver serializa essa propriedade, ele converte a hora para UTC, o formato padrão para horas armazenadas no MongoDB.
public class PatientRecord { public Guid Id { get; set; } [ ] public DateTime AppointmentTime { get; set; } }
Você também pode especificar uma ou ambas as opções do DateTime
anteriores ao registrar o mapa de classe:
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMap.MapMember(p => p.DateOfBirth) .SetSerializer(new DateTimeSerializer(dateOnly: true)); classMap.MapMember(p => p.AppointmentTime) .SetSerializer(new DateTimeSerializer(DateTimeKind.Local)); });
Dica
Valores de DateTimeKind
a enumeração de DateTimeKind
faz parte do framework .NET. Para mais informações sobre seus nós, consulte a documentação da Microsoft de enumeração de DateTimeKind.
Personalize a serialização do dicionário
a enumeração de DictionaryRepresentation
define os formatos aos quais o driver .NET/C# pode serializar uma instância do Dictionary
. Esta enumeração inclui os seguintes nós:
Documento: (Padrão) o driver serializa o
Dictionary
para umBsonDocument
. Cada entrada no dicionário é umBsonElement
com um nome igual à chave da entrada e um valor igual ao valor da entrada. Você pode usar essa representação somente quando todas as chaves do dicionário forem strings que também sejam nomesBsonElement
válidos.ArrayOfArrays: o driver serializa o dicionário para um
BsonArray
. Cada entrada no dicionário é umBsonArray
aninhado de dois elementos que contém a chave e o valor da entrada.ArrayOfDocuments: o driver serializa o dicionário para um
BsonArray
. Cada entrada no dicionário é umBsonDocument
aninhado no formato{ k : key, v : value }
. Como as chaves e os valores são marcados com nomes de elementos, você pode fazer consulta desse formato de forma mais intuitiva do que umArrayOfArrays
.
No exemplo de código abaixo, a propriedade RoomSizes
é um dicionário que contém cada quarto de uma casa e seu tamanho correspondente. O atributo [BsonDictionaryOptions()]
instrui o driver .NET/C# a serializar esta propriedade para um objeto BsonArray
e cada entrada no dicionário para um BsonDocument
do formulário { k : "<room>", v : <size> }
.
public class House { public Guid Id { get; set; } [ ] public Dictionary<string, float> RoomSizes { get; set; } }
Você também pode especificar o formato de serialização de um dicionário ao registrar o mapa de classe, conforme o exemplo abaixo:
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMAp.MapMember(h => h.RoomSizes) .SetSerializer(new DictionaryInterfaceImplementerSerializer<Dictionary<string, float>> (DictionaryRepresentation.ArrayOfDocuments)); });
Exemplo
O exemplo abaixo mostra como inserir um documento de Clothing
com especificações de mapeamento de campo personalizadas no MongoDB.
O código abaixo define a classe Clothing
com estes atributos relacionados à serialização:
[BsonElement()]
, que especifica os nomes de campos personalizados na convenção de nomenclatura Camel case[BsonRepresentation()]
, que especifica a serialização do campoPrice
como um tipoDouble
de BSON[BsonDefaultValue()]
, que define a propriedadeName
como"Generic item"
se nenhum valor tiver sido atribuído a ela[BsonDateTimeOptions(DateOnly = true)]
, que especifica que a propriedadeDateTime
representa somente um valor de data, sem hora associada
public class Clothing { public ObjectId Id { get; set; } [ ] [ ] public string Name { get; set; } [ ] public bool InStock { get; set; } [ ] [ ] public decimal Price { get; set; } [ ] public List<string> ColorSelection { get; set; } [ ] [ ] public DateTime ListedDate { get; set; } [ ] public Dictionary<string, string> SizeGuide { get; set; } }
O código abaixo instancia um objeto Clothing
e insere o documento em uma coleção:
var doc = new Clothing { Name = "Denim Jacket", InStock = false, Price = 32.99m, ColorSelection = new List<string> { "dark wash", "light wash" }, ListedDate = DateTime.Parse("Jan 1, 2007"), SizeGuide = new Dictionary<string, string>() { {"Small", "Chest: 38\", Waist: 38\", Shoulders: 15\""}, {"Medium", "Chest: 40\", Waist: 40\", Shoulders: 15.5\""}, {"Large", "Chest: 42\", Waist: 40\", Shoulders: 16\""} } }; _myColl.InsertOne(doc);
A representação BSON do documento inserido é semelhante a esta:
{ "_id": ObjectId("..."), "name": "Denim Jacket", "inStock": false, "price": 32.99, "colorSelection": [ "dark wash", "light wash" ], "listedDate" : ISODate("2007-01-01T00:00:00Z"), "sizeGuide" : { "Small" : "Chest: 38\", Waist: 38\", Shoulders: 15\"", "Medium" : "Chest: 40\", Waist: 40\", Shoulders: 15.5\"", "Large" : "Chest: 42\", Waist: 40\", Shoulders: 16\"" } }
Informações adicionais
Para obter uma lista completa de atributos relacionados à serialização, consulte a documentação da API Serialization.Attributes.
Para mais exemplos de operações de leitura e gravação usando POCOs, consulte os exemplos de uso ou as Páginas de introdução a CRUD.
Para saber mais sobre como o driver mapeia documentos BSON para POCOs, consulte Mapeamento de classe.
Documentação da API
Para saber mais sobre qualquer um dos métodos ou tipos discutidos neste guia, consulte a seguinte documentação da API: