Overview
En esta guía, podrá aprender cómo utilizar "ObjetosCLR/de clasesimples, o POCO, con el controlador .NET/C# para sus operaciones y consultas. Los POCO son objetos de clase simples que no heredan características de ninguna clase base o interfaz específica del framework. Recomendamos usar POCO en su código C# para cumplir con el uso idiomático del controlador y lograr el mejor rendimiento.
Lea esta guía si desea obtener más información sobre cómo usar POCO con el controlador .NET/C# o si debe ajustar el comportamiento de mapeo de campos predeterminado del controlador.
Crear un POCO
Puedes crear un POCO definiendo una clase simple que no implemente interfaces ni extienda clases de un framework. Al ejecutar una operación, como una lectura o escritura, con un POCO, el controlador serializa o convierte internamente el POCO a BSON.
Seleccione el POCO o la pestaña BSON para ver cómo el controlador serializa una muestra de POCO a 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" ] }
Puede definir un POCO con cualquier estructura de objeto que se adapte a sus necesidades, incluidos objetos anidados, matrices, listas y cualquier tipo de datos.
Serialización personalizada
Si el comportamiento predeterminado de asignación de campos no satisface sus necesidades, puede especificar un comportamiento personalizado mediante atributos relacionados con la serialización. Estos atributos modifican la forma en que el controlador serializa cada propiedad de su POCO. Esta sección describe algunos atributos comunes relacionados con la serialización.
Serializar propiedades de solo lectura
Si una propiedad es de solo lectura, el automapper no la incluye en el mapa de clases para la serialización. Para forzar al automapper a incluir una propiedad en el mapa de clases, aplique la
[BsonElement] atribuir a la propiedad.
El siguiente ejemplo de código aplica el atributo [BsonElement] a la propiedad Upc de la clase Clothing. Upc es una propiedad de solo lectura porque tiene un método get pero ningún 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; } }
También puede agregar una propiedad de solo lectura al registrar el mapa de clase, como se muestra en el siguiente ejemplo:
BsonClassMap.RegisterClassMap<Clothing>(classMap => { classMap.AutoMap(); classMap.MapProperty(c => c.Upc); });
Nota
Cuando el controlador .NET/C# serializa una propiedad de solo lectura, la propiedad y su valor se almacenan en la base de datos, pero nunca se deserializan nuevamente.
Establecer nombres de campos
El controlador serializa las propiedades POCO en campos BSON con el mismo nombre y mayúsculas. Para almacenar una propiedad con un nombre diferente, utilice el atributo [BsonElement()]. El siguiente código asigna la propiedad YearBuilt de la clase House al campo year_built del documento BSON serializado:
public class House { public Guid Id { get; set; } [] public int YearBuilt { get; set; } }
Si bien es común utilizar la convención de nombres de Pascal al definir clases de C#, el uso del atributo [BsonElement()] le permite seleccionar una convención de nombres diferente o personalizada en su colección MongoDB.
Tip
Establecer la convención de nombre de campo personalizado
Si desea serializar cada propiedad con un nombre de campo personalizado, puede definir un atributo ConventionPack en lugar de usar el atributo [BsonElement()]. Por ejemplo, si define su clase usando la convención de nomenclatura Pascal, puede usar el siguiente código para usar nombres de campo CamelCase en el documento serializado:
var camelCaseConvention = new ConventionPack { new CamelCaseElementNameConvention() }; ConventionRegistry.Register("CamelCase", camelCaseConvention, type => true);
Para obtener más información sobre las convenciones, consulte la Secciónde convenciones de la guía de serialización.
Seleccionar tipo de representación
Para serializar una propiedad de C# a un tipo BSON específico, use el atributo [BsonRepresentation()]. Esto solo funciona si el tipo primitivo de C# es convertible al tipo BSON especificado.
En el siguiente ejemplo de código, el controlador serializa la propiedad YearBuilt, definida como char en C#, como un tipo BSON Int32:
public class House { public Guid Id { get; set; } [] public char YearBuilt { get; set; } }
Para obtener más información sobre las conversiones de tipos válidas, consulte la Especificación de conversiones de C#.
Importante
Serialización de NaN e Infinity
Si intenta serializar o deserializar un valor de punto flotante Infinity o NaN a una representación integral, el controlador lanza un OverflowException.
Establecer orden de campos
El controlador serializa las propiedades en los campos BSON en el orden en que se especifican en el POCO. Para almacenar las propiedades en un orden personalizado que coincida con un esquema existente, puede especificar el parámetro con nombre Order en el atributo [BsonElement()]. En el siguiente ejemplo de código, el controlador almacena la propiedad YearBuilt después de la propiedad Style:
public class House { public Guid Id { get; set; } [] public int YearBuilt { get; set; } [] public string Style { get; set; } }
Si alguna propiedad no tiene explícitamente un Order, el driver las serializará en el orden por defecto después de aquellas que sí lo tengan.
Identificar Id la propiedad
Por defecto, el controlador asigna cualquier propiedad pública llamada Id, id, o _id al campo BSON _id. Para seleccionar explícitamente la propiedad que se asignará al campo _id, utiliza el atributo [BsonId()]. El siguiente ejemplo de código asigna la propiedad Identifier al campo _id:
public class House { [] public string Identifier { get; set; } }
Advertencia
Campos de identificación múltiples
Si identifica más de una propiedad como el campo _id mediante el atributo [BsonId()], el controlador genera un error DuplicateBsonMemberMapAttributeException. Si especifica el mismo campo de base de datos más de una vez (por ejemplo, si su POCO incluye las propiedades Id y _id), el controlador genera un error BsonSerializationException.
Nota
Identificadores de documentos anidados
La lógica de mapeo del campo _id descrita en esta sección solo se aplica al documento raíz y no se aplica a los documentos anidados.
Especificar un generador de ID
Cada documento de una colección de MongoDB debe tener un ID único. Al serializar un objeto en una colección, si su propiedad ID contiene el valor predeterminado para su tipo de dato (normalmente null), el controlador .NET/C# no serializa dicho valor. En su lugar, intenta generar un valor de ID único y asignarlo a la propiedad.
Para habilitar la generación de ID para una propiedad, debe especificar el generador de ID que el controlador utiliza para ella. Puede hacerlo aplicando el atributo [BsonId] a la propiedad y pasando el argumento IdGenerator para especificar el tipo de generador. La siguiente tabla describe los generadores de ID disponibles en el controlador .NET/C#:
Tipo de datos del campo Id | Cómo utilizar | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Para utilizar el algoritmo COMB para generar un valor Para generar un valor único Para obtener más información, consulte la guía de GUID. | ||||||||||
| El controlador utiliza automáticamente el tipo | ||||||||||
| Si especifica que una propiedad de ID con el tipo de dato Para generar un valor | ||||||||||
| Aplique el atributo |
Alternativamente, puede especificar un tipo IIdGenerator cuando registre el mapa de clase, como se muestra en el siguiente ejemplo:
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMap.MapIdMember(h => h.Id).SetIdGenerator(CombGuidGenerator.Instance); });
Tip
Especificar un IIdGenerator para múltiples clases
Puede usar el método RegisterIdGenerator() para especificar un único IIdGenerator para todas las propiedades Id de un tipo de dato determinado. El siguiente ejemplo de código indica al controlador que use el tipo CombGuidGenerator para todos los ID Guid:
BsonSerializer.RegisterIdGenerator( typeof(Guid), CombGuidGenerator.Instance );
El controlador .NET/C# también incluye tipos IIdGenerator que validan la propiedad Id y generan una excepción si el ID no es válido. La siguiente tabla enumera estos tipos:
Validación de identidad | Tipo de generador IId |
|---|---|
No nulo |
|
No todos son ceros |
|
En el siguiente ejemplo de código, si la propiedad Id de la clase House contiene el valor predeterminado (null), el controlador genera una excepción:
public class House { [] public Guid Id { get; set; } }
Omitir campos
Para evitar que el controlador serialice un campo específico, utilice el atributo [BsonIgnore]. El siguiente código muestra cómo evitar que el controlador serialice la propiedad YearBuilt:
public class House { public Guid Id { get; set; } [] public int YearBuilt { get; set; } public string Style { get; set; } }
Incluso si define la propiedad YearBuilt, el campo no se guarda en MongoDB.
Nota
Puede definir un mapa de clases para evitar la serialización de campos específicos. Para obtener más información y ver un ejemplo, consulte la sección "Omitir campos" de la guía de mapeo de clases.
Omitir campos vacíos
De forma predeterminada, el controlador serializa las propiedades no inicializadas con valores null. Para ignorar las propiedades vacías durante la serialización, utilice el atributo [BsonIgnoreIfNull]. El siguiente código muestra cómo evitar que el controlador serialice la propiedad Style si no está inicializada:
public class House { public Guid Id { get; set; } [] public string Style { get; set; } public int YearBuilt { get; set; } }
También puede indicarle al controlador que ignore una propiedad que contenga un valor null cuando registre el mapa de clase, como se muestra en el siguiente ejemplo:
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMap.MapMember(h => h.Style).SetIgnoreIfNull(true); });
Nota
Propiedades de Tipo de Valor
No puede usar el [BsonIgnoreIfNull] atributo ni el SetIgnoreIfNull() método para evitar que se serialicen propiedades de tipo de valor no inicializadas, a menos que las marque como nulas. En su lugar, use el [BsonIgnoreIfDefault] atributo o el método de SetIgnoreIfDefault() mapa de clase, que se describen en la sección "Personalizar valores predeterminados" de esta guía.
Personalizar valores predeterminados
En C#, una propiedad tiene un valor predeterminado hasta que se le asigna uno. El valor predeterminado depende del tipo de dato de la propiedad. Por ejemplo, el valor predeterminado para una propiedad de tipo referencia es null.
Para especificar un valor predeterminado diferente para una propiedad, aplique el atributo [BsonDefaultValue()] a la propiedad y pase el valor predeterminado deseado como argumento.
Los siguientes ejemplos de código aplican el atributo [BsonDefaultValue()] a la propiedad YearBuilt. Hasta que se le asigne un valor a esta propiedad, su valor es 1900.
public class House { public Guid Id { get; set; } [] public int YearBuilt { get; set; } }
También puede especificar un valor predeterminado diferente para una propiedad cuando registra el mapa de clase, como se muestra en el siguiente ejemplo:
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMap.MapMember(h => h.YearBuilt).SetDefaultValue(1900); });
De forma predeterminada, el controlador .NET/C# serializa todas las propiedades, incluidas aquellas con valores predeterminados. Para indicarle al controlador que ignore una propiedad con el valor predeterminado, utilice el atributo [BsonIgnoreIfDefault].
El siguiente ejemplo de código aplica el atributo [BsonIgnoreIfDefault] a la propiedad YearBuilt. Si el valor de esta propiedad es el predeterminado para su tipo de dato (0 para las propiedades int), el controlador no lo serializará.
public class House { public Guid Id { get; set; } [] public int YearBuilt { get; set; } }
También puede indicarle al controlador que ignore una propiedad que contenga el valor predeterminado cuando registre el mapa de clase, como se muestra en el siguiente ejemplo:
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMap.MapMember(h => h.YearBuilt).SetIgnoreIfDefault(true); });
Puede especificar un valor predeterminado diferente para una propiedad e indicar al controlador que la ignore si contiene dicho valor. Para ello, aplique los atributos [BsonDefaultValue()] y [BsonIgnoreIfDefault] a la propiedad, como se muestra en el siguiente ejemplo de código:
public class House { public Guid Id { get; set; } [] [] public int YearBuilt { get; set; } }
El ejemplo de código anterior establece el siguiente comportamiento de serialización:
Si no se ha asignado un valor a la propiedad
YearBuilt, tiene el valor predeterminado especificado de1900.Dado que
1900es el valor predeterminado para esta propiedad, el controlador ignorará la propiedad si tiene este valor.
Personalizar la serialización de DateTime
Para personalizar cómo el controlador .NET/C# serializa las propiedades DateTime, utilice el atributo [BsonDateTimeOptions()] y especifique la configuración deseada como argumento.
Si una propiedad DateTime representa solo una fecha, puede aplicarle el atributo [BsonDateTimeOptions(DateOnly = true)]. Si lo hace, el controlador no realizará ninguna conversión de zona horaria en el valor.
En el siguiente ejemplo de código, la clase PatientRecord usa un DateTime para la propiedad DateOfBirth. El atributo [BsonDateTimeOptions(DateOnly = true)] indica que la propiedad solo contiene una fecha.
public class PatientRecord { public Guid Id { get; set; } [] public DateTime DateOfBirth { get; set; } }
También puede usar el atributo [BsonDateTimeOptions()] para especificar el DateTimeKind de una propiedad DateTime. En el siguiente ejemplo de código, la clase PatientRecord tiene una propiedad AppointmentTime de tipo DateTime. El atributo [BsonDateTimeOptions(Kind = DateTimeKind.Local)] indica que el componente de tiempo del valor de la propiedad está en hora local. Cuando el controlador serializa esta propiedad, convierte la hora a UTC, el formato estándar para las horas almacenadas en MongoDB.
public class PatientRecord { public Guid Id { get; set; } [] public DateTime AppointmentTime { get; set; } }
También puede especificar una o ambas de las opciones DateTime anteriores al registrar el mapa de clase:
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)); });
Tip
DateTimeKind Values
La DateTimeKind enumeración forma parte de .NET Framework. Para obtener más información sobre sus miembros, consulte la documentación de Microsoft sobre la enumeración DateTimeKind.
Serialización personalizada de solo fecha
Para personalizar cómo el controlador .NET/C# serializa las propiedades DateOnly, [BsonDateOnlyOptions()] utilice el atributo y especifique las siguientes configuraciones:
Representation:Establezca una instanciaBsonTypeque especifica cómo se almacena el valorDateOnlyen MongoDB.DocumentFormatEsta opción solo se aplica si se establece la propiedadRepresentationenBsonType.Document; de lo contrario, se ignora. Puede establecerDocumentFormaten uno de los siguientes valores de enumeraciónDateOnlyDocumentFormat:DateTimeTicks(predeterminado): el documento contiene los camposDateTime(BsonType.DateTime) yTicks(BsonType.Int64)YearMonthDay:El documento contiene los camposYear,MonthyDay, que tienen valoresBsonType.Int32
En el siguiente ejemplo de código, la clase PatientRecord contiene una propiedad DateOfBirth con un valor DateOnly. El atributo indica al controlador que almacene el valor como un documento anidado que contiene los campos para el año, mes y día especificados.
public class PatientRecord { public Guid Id { get; set; } [] public DateOnly DateOfBirth { get; set; } }
Tip
Utilice DateOnlySerializer para establecer el comportamiento global
En lugar de utilizar el atributo [BsonDateOnlyOptions()] en el nivel de propiedad, puede registrar un objeto DateOnlySerializer para aplicar el comportamiento de serialización globalmente:
BsonSerializer.RegisterSerializer( new DateOnlySerializer(BsonType.Document, DateOnlyDocumentFormat.YearMonthDay) );
Personalizar la serialización del diccionario
La enumeración DictionaryRepresentation define los formatos en los que el controlador .NET/C# puede serializar una instancia Dictionary. Esta enumeración incluye los siguientes miembros:
Documento: (Predeterminado) El controlador serializa
DictionaryBsonDocumentcomo. Cada entrada del diccionario es unBsonElementcon un nombre igual a la clave de la entrada y un valor igual al valor de la entrada. Esta representación solo se puede usar cuando todas las claves del diccionario son cadenas que también sonBsonElementnombres válidos.ArrayOfArrays: El controlador serializa el diccionario en
BsonArrayun. Cada entrada del diccionario es un anidado de dos elementosBsonArrayque contiene la clave y el valor de la entrada.ArrayOfDocuments: El controlador serializa el diccionario en
BsonArrayun. Cada entrada del diccionario es un anidadoBsonDocument{ k : key, v : value }con el formato. Dado que las claves y los valores están etiquetados con nombres de elementos, se puede consultar este formato de forma más intuitiva que conArrayOfArraysun.
En el siguiente ejemplo de código, la propiedad RoomSizes es un diccionario que contiene cada habitación de una casa y su tamaño correspondiente. El atributo [BsonDictionaryOptions()] indica al controlador .NET/C# que serialice esta propiedad en un objeto BsonArray y cada entrada del diccionario en un objeto BsonDocument con la forma { k : "<room>", v : <size> }.
public class House { public Guid Id { get; set; } [] public Dictionary<string, float> RoomSizes { get; set; } }
También puede especificar el formato de serialización de un diccionario cuando registra el mapa de clase, como se muestra en el siguiente ejemplo:
BsonClassMap.RegisterClassMap<House>(classMap => { classMap.AutoMap(); classMAp.MapMember(h => h.RoomSizes) .SetSerializer(new DictionaryInterfaceImplementerSerializer<Dictionary<string, float>> (DictionaryRepresentation.ArrayOfDocuments)); });
Ejemplo
El siguiente ejemplo muestra cómo insertar un documento Clothing con especificaciones de mapeo de campos personalizados en MongoDB.
El siguiente código define la clase Clothing con estos atributos relacionados con la serialización:
[BsonElement()], que especifica nombres de campos personalizados en la convención de nomenclatura Camel Case[BsonRepresentation()], que especifica la serialización del campoPricecomo un tipo BSONDouble[BsonDefaultValue()], que establece la propiedadNameen"Generic item"si no se le ha asignado ningún valor[BsonDateTimeOptions(DateOnly = true)], que especifica que la propiedadDateTimerepresenta solo un valor de fecha, sin tiempo asociado
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; } }
El siguiente código instancia un objeto Clothing e inserta el documento en una colección:
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);
La representación BSON del documento insertado se ve así:
{ "_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\"" } }
Información Adicional
Para obtener una lista completa de los atributos relacionados con la serialización, consulte la documentación de la API Serialization.Attributes.
Para obtener más información sobre cómo el controlador asigna documentos BSON a POCO, consulte Asignación de clases.
Documentación de la API
Para aprender más sobre cualquiera de los métodos o tipos analizados en esta guía, consulta la siguiente documentación de API: