|
| 1 | +.. _csharp-poco: |
| 2 | + |
| 3 | +=============== |
| 4 | +Work with POCOs |
| 5 | +=============== |
| 6 | + |
| 7 | +.. default-domain:: mongodb |
| 8 | + |
| 9 | +.. contents:: On this page |
| 10 | + :local: |
| 11 | + :backlinks: none |
| 12 | + :depth: 2 |
| 13 | + :class: singlecol |
| 14 | + |
| 15 | +Overview |
| 16 | +-------- |
| 17 | + |
| 18 | +In this guide, you can learn about how you can use ":wikipedia:`Plain Old CLR/Class |
| 19 | +Objects <Plain_old_CLR_object>`", or **POCOs**, with the {+driver-short+} for your operations |
| 20 | +and queries. POCOs are simple class objects that do not inherit |
| 21 | +features from any framework-specific base class and do not return any |
| 22 | +special types. We recommend using POCOs in your {+language+} code to |
| 23 | +adhere to idiomatic driver usage and achieve the best performance. |
| 24 | + |
| 25 | +You should read this guide if you want to learn more about how to use |
| 26 | +POCOs with the {+driver-short+} or if you need to adjust the driver's default |
| 27 | +field mapping behavior. |
| 28 | + |
| 29 | +Create a POCO |
| 30 | +------------- |
| 31 | + |
| 32 | +You can create a POCO by defining a simple class that does not |
| 33 | +implement interfaces or extend classes from a framework. When you |
| 34 | +execute an operation such as a read or write using a POCO, the driver |
| 35 | +internally *serializes*, or converts, the POCO to BSON. |
| 36 | + |
| 37 | +Select the :guilabel:`POCO` or :guilabel:`BSON` tab to see how the |
| 38 | +driver serializes a sample POCO to BSON: |
| 39 | + |
| 40 | +.. tabs:: |
| 41 | + |
| 42 | + .. tab:: POCO |
| 43 | + :tabid: poco-representation |
| 44 | + |
| 45 | + .. code-block:: csharp |
| 46 | + :copyable: false |
| 47 | + |
| 48 | + public class Clothing |
| 49 | + { |
| 50 | + public ObjectId Id { get; set; } |
| 51 | + public string Name { get; set; } |
| 52 | + public bool InStock { get; set; } |
| 53 | + public double Price { get; set; } |
| 54 | + public List<string> ColorSelection { get; set; } |
| 55 | + } |
| 56 | + |
| 57 | + .. tab:: BSON |
| 58 | + :tabid: bson-representation |
| 59 | + |
| 60 | + .. code-block:: json |
| 61 | + :copyable: false |
| 62 | + |
| 63 | + { |
| 64 | + "_id": ObjectId("..."), |
| 65 | + "Name": "Long Sleeve Shirt", |
| 66 | + "InStock": true, |
| 67 | + "Price": 17.99, |
| 68 | + "ColorSelection": [ "black", "navy", "red" ] |
| 69 | + } |
| 70 | + |
| 71 | +You can define a POCO with any object structure that suits your |
| 72 | +needs, including nested objects, arrays, lists, and any data types. |
| 73 | + |
| 74 | +Custom Serialization |
| 75 | +-------------------- |
| 76 | + |
| 77 | +If the default field mapping behavior does not meet your needs, you can |
| 78 | +specify custom behavior using serialization-related attributes. These |
| 79 | +attributes change the way that the driver serializes each property of |
| 80 | +your POCO. This section describes some of the common |
| 81 | +serialization-related attributes. |
| 82 | + |
| 83 | +Set Field Names |
| 84 | +~~~~~~~~~~~~~~~ |
| 85 | + |
| 86 | +The driver serializes POCO properties to BSON fields with the same field |
| 87 | +name and capitalization. To store a property under a different name, use |
| 88 | +the ``[BsonElement()]`` attribute. The following code maps the |
| 89 | +``YearBuilt`` property of the ``House`` class to the ``year_built`` |
| 90 | +field in the serialized BSON document: |
| 91 | + |
| 92 | +.. code-block:: csharp |
| 93 | + :copyable: true |
| 94 | + |
| 95 | + public class House |
| 96 | + { |
| 97 | + public ObjectId Id { get; set; } |
| 98 | + |
| 99 | + [BsonElement("year_built")] |
| 100 | + public int YearBuilt { get; set; } |
| 101 | + } |
| 102 | + |
| 103 | +Though it is common to use the Pascal case naming convention when |
| 104 | +defining {+language+} classes, using the ``[BsonElement()]`` attribute |
| 105 | +allows you to select a different or custom naming convention in your |
| 106 | +MongoDB collection. |
| 107 | + |
| 108 | +.. tip:: Set Custom Field Name Convention |
| 109 | + |
| 110 | + If you want to serialize every property with a custom field name, you |
| 111 | + can define a ``ConventionPack`` instead of using the |
| 112 | + ``[BsonElement()]`` attribute. For example, if you define your class |
| 113 | + using the Pascal case naming convention, you can use the following |
| 114 | + code to use camel case field names in the serialized document: |
| 115 | + |
| 116 | + .. literalinclude:: ../includes/fundamentals/code-examples/poco.cs |
| 117 | + :start-after: start-conventionpack |
| 118 | + :end-before: end-conventionpack |
| 119 | + :language: csharp |
| 120 | + :copyable: |
| 121 | + :dedent: |
| 122 | + |
| 123 | +Select Type Representation |
| 124 | +~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 125 | + |
| 126 | +To serialize a {+language+} property to a specific BSON type, use the |
| 127 | +``[BsonRepresentation()]`` attribute. This works only if the |
| 128 | +{+language+} primitive type is convertible to the BSON type you specify. |
| 129 | +In the following code sample, the ``YearBuilt`` property, defined as a |
| 130 | +``char`` in {+language+}, is serialized as a BSON ``Int32`` type: |
| 131 | + |
| 132 | +.. code-block:: csharp |
| 133 | + :copyable: true |
| 134 | + |
| 135 | + public class House |
| 136 | + { |
| 137 | + public ObjectId Id { get; set; } |
| 138 | + |
| 139 | + [BsonRepresentation(BsonType.Int32)] |
| 140 | + public char YearBuilt { get; set; } |
| 141 | + } |
| 142 | + |
| 143 | +For more information on valid type conversions, see the `{+language+} |
| 144 | +Conversions Specification |
| 145 | +<https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/conversions>`__. |
| 146 | + |
| 147 | +Set Field Order |
| 148 | +~~~~~~~~~~~~~~~ |
| 149 | + |
| 150 | +The driver serializes properties to BSON fields in the order they |
| 151 | +are specified in the POCO. To store properties in a custom order to |
| 152 | +match an existing schema, you can specify the ``Order`` named |
| 153 | +parameter in the ``[BsonElement()]`` attribute. In the following code |
| 154 | +sample, the driver stores the ``YearBuilt`` property after the |
| 155 | +``Style`` property: |
| 156 | + |
| 157 | +.. code-block:: csharp |
| 158 | + :copyable: true |
| 159 | + |
| 160 | + public class House |
| 161 | + { |
| 162 | + public ObjectId Id { get; set; } |
| 163 | + |
| 164 | + [BsonElement(Order = 2)] |
| 165 | + public int YearBuilt { get; set; } |
| 166 | + |
| 167 | + [BsonElement(Order = 1)] |
| 168 | + public string Style { get; set; } |
| 169 | + } |
| 170 | + |
| 171 | +If any properties don't have an explicit ``Order``, the driver will |
| 172 | +serialize them in the default order after those that do. |
| 173 | + |
| 174 | +Identify ``Id`` Property |
| 175 | +~~~~~~~~~~~~~~~~~~~~~~~~ |
| 176 | + |
| 177 | +By default, the driver maps any public property named ``Id``, ``id``, or |
| 178 | +``_id`` to the BSON ``_id`` field. To explicitly select the |
| 179 | +property to map to the ``_id`` field, use the ``[BsonId()]`` attribute. |
| 180 | +The following code sample maps the ``Identifier`` property to the |
| 181 | +``_id`` field: |
| 182 | + |
| 183 | +.. code-block:: csharp |
| 184 | + :copyable: true |
| 185 | + |
| 186 | + public class House |
| 187 | + { |
| 188 | + [BsonId] |
| 189 | + public string Identifier { get; set; } |
| 190 | + } |
| 191 | + |
| 192 | +.. warning:: Multiple Id Fields |
| 193 | + |
| 194 | + If you identify more than one property as the ``_id`` field using the |
| 195 | + ``[BsonId()]`` attribute, the driver throws a |
| 196 | + ``DuplicateBsonMemberMapAttributeException``. If your POCO |
| 197 | + properties use more than one of the three recognized field |
| 198 | + names (``Id``, ``id``, and ``_id``), the driver throws a |
| 199 | + ``BsonSerializationException``. |
| 200 | + |
| 201 | +Omit Empty Fields |
| 202 | +~~~~~~~~~~~~~~~~~ |
| 203 | + |
| 204 | +By default, the driver serializes undefined properties to fields with ``null`` |
| 205 | +values. To ignore undefined properties during serialization, use the ``[BsonIgnore()]`` |
| 206 | +attribute. The following code shows how you can prevent the driver from |
| 207 | +serializing the ``YearBuilt`` property if it is undefined: |
| 208 | + |
| 209 | +.. code-block:: csharp |
| 210 | + :copyable: true |
| 211 | + |
| 212 | + public class House |
| 213 | + { |
| 214 | + public ObjectId Id { get; set; } |
| 215 | + |
| 216 | + [BsonIgnore] |
| 217 | + public int YearBuilt { get; set; } |
| 218 | + public string Style { get; set; } |
| 219 | + } |
| 220 | + |
| 221 | +Example |
| 222 | +------- |
| 223 | + |
| 224 | +The following example shows how to insert a ``Clothing`` document with custom field |
| 225 | +mapping specifications into MongoDB. |
| 226 | + |
| 227 | +The following code defines the ``Clothing`` class with these |
| 228 | +serialization-related attributes: |
| 229 | + |
| 230 | +- ``[BsonElement()]``, which specifies custom field names in the camel case naming convention |
| 231 | +- ``[BsonRepresentation()]``, which specifies serialization of the ``Price`` field as a BSON ``Double`` type |
| 232 | + |
| 233 | +.. literalinclude:: ../includes/fundamentals/code-examples/poco.cs |
| 234 | + :start-after: start-model |
| 235 | + :end-before: end-model |
| 236 | + :language: csharp |
| 237 | + :copyable: |
| 238 | + :dedent: |
| 239 | + |
| 240 | +The following code instantiates a ``Clothing`` object and inserts the document into a collection: |
| 241 | + |
| 242 | +.. literalinclude:: ../includes/fundamentals/code-examples/poco.cs |
| 243 | + :start-after: start-insert |
| 244 | + :end-before: end-insert |
| 245 | + :language: csharp |
| 246 | + :copyable: |
| 247 | + :dedent: |
| 248 | + |
| 249 | +The BSON representation of the inserted document looks like this: |
| 250 | + |
| 251 | +.. code-block:: json |
| 252 | + :copyable: false |
| 253 | + |
| 254 | + { |
| 255 | + "_id": ObjectId("..."), |
| 256 | + "name": "Denim Jacket", |
| 257 | + "inStock": false, |
| 258 | + "price": 32.99, |
| 259 | + "colorSelection": [ "dark wash", "light wash" ] |
| 260 | + } |
| 261 | + |
| 262 | +Additional Information |
| 263 | +---------------------- |
| 264 | + |
| 265 | +For a full list of serialization-related attributes, see the |
| 266 | +`Serialization.Attributes API documentation <{+api-root+}/N_MongoDB_Bson_Serialization_Attributes.htm>`__. |
| 267 | + |
| 268 | +For additional read and write operation examples using POCOs, see the :ref:`Usage Examples |
| 269 | +<csharp-usage-examples>` or the :ref:`CRUD Fundamentals Pages <csharp-crud>`. |
| 270 | + |
| 271 | +API Documentation |
| 272 | +~~~~~~~~~~~~~~~~~ |
| 273 | + |
| 274 | +To learn more about any of the methods or types discussed in this |
| 275 | +guide, see the following API documentation: |
| 276 | + |
| 277 | +- `[BsonElement()] <{+api-root+}/T_MongoDB_Bson_Serialization_Attributes_BsonElementAttribute.htm>`__ |
| 278 | +- `[BsonRepresentation()] <{+api-root+}/T_MongoDB_Bson_Serialization_Attributes_BsonRepresentationAttribute.htm>`__ |
| 279 | +- `[BsonId()] <{+api-root+}/T_MongoDB_Bson_Serialization_Attributes_BsonIdAttribute.htm>`__ |
| 280 | +- `[BsonIgnore()] <{+api-root+}/T_MongoDB_Bson_Serialization_Attributes_BsonIgnoreAttribute.htm>`__ |
| 281 | +- `ConventionPack <{+api-root+}/T_MongoDB_Bson_Serialization_Conventions_ConventionPack.htm>`__ |
| 282 | +- `InsertOne() <{+api-root+}/M_MongoDB_Driver_IMongoCollection_1_InsertOne.htm>`__ |
0 commit comments