Skip to content

DOCSP-43419 - GuidRepresentationMode #235

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
188 changes: 110 additions & 78 deletions source/fundamentals/serialization/guid-serialization.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,87 +24,119 @@ In this guide, you can learn how to serialize **globally unique identifiers**
(`GUIDs <https://learn.microsoft.com/en-us/dynamicsax-2012/developer/guids>`__),
also known as **universally unique identifiers** (UUIDs).

.. tip::
.. tip:: ObjectId

In MongoDB applications, ``ObjectId`` can be used as a unique identifier for
a document. Consider using ``ObjectId`` in place of a GUID with MongoDB
applications where possible.
In MongoDB applications, you can use the
`ObjectId <{+new-api-root+}/api/MongoDB.Bson/MongoDB.Bson.ObjectId.html>`__ type
as a unique identifier for a document. Consider using ``ObjectId`` instances in place
of GUIDs in MongoDB applications where possible.

A GUID is a 16-byte integer that you can use as a unique ID for a MongoDB document.
Originally, GUIDs in MongoDB were represented as ``BsonBinaryData`` values of subtype 3.
Subtype 3 did not standardize the byte order during serialization, which led to
inconsistent serialization across MongoDB drivers.
To standardize the byte order and ensure consistent serialization across drivers, we
created ``BsonBinaryData`` subtype 4.
GUIDs in MongoDB
----------------

.. note::

Use ``BsonBinaryData`` subtype 4 for all new GUIDs.
A GUID is a 16-byte integer that you can use as a unique ID for a MongoDB document.
The following code block shows an example GUID:

GuidRepresentationMode
----------------------
.. code-block::
:copyable: false

In many MongoDB collections, all GUID fields use the same subtype of ``BsonBinaryData``.
Some older collections, however, may contain some GUID fields that
use subtype 3 and others that use subtype 4.
To ensure that the driver serializes and deserializes all GUIDs correctly,
you should set the ``BsonDefaults.GuidRepresentationMode`` property to one of the
following ``GuidRepresentationMode`` values:
00112233-4455-6677-8899-aabbccddeeff

V2
~~
Originally, MongoDB represented GUIDs as ``BsonBinaryData``
values of :manual:`subtype 3. </reference/bson-types/#binary-data>`
Because subtype 3 didn't standardize the byte order of GUIDs
during encoding, different MongoDB drivers encoded GUIDs with different byte orders.

``GuidRepresentationMode.V2`` assumes that all GUIDs in a document use the same
``BsonBinaryData`` subtype. In this mode, GUID representation is
controlled by the reader or writer, not the serializer.
The following tabs show different driver encodings of the preceding GUID to
``BsonBinaryData`` subtype 3:

``V2`` is the default ``GuidRepresentationMode``.
.. tabs::

.. note::

When version 3 of the {+driver-short+} is released, support for ``GuidRepresentationMode.V2``
will be removed from the driver and ``V3`` will become the default.
.. tab:: {+driver-short+}
:tabid: csharp

V3
~~
.. code-block:: csharp
:copyable: false

``GuidRepresentationMode.V3`` allows fields in the same document to use different
GUID formats.
In this mode, GUID representation is controlled at the property level by configuring the
serializer for each property.
33221100-5544-7766-8899-aabbccddeeff

To use ``GuidRepresentationMode.V3``, run the following line of code. You should run this
code during the bootstrapping phase of your application, before creating
a ``MongoClient`` object.
.. tab:: PyMongo
:tabid: pymongo

.. code-block:: csharp
.. code-block:: python
:copyable: false

00112233-4455-6677-8899-aabbccddeeff

.. tab:: Java Driver
:tabid: java

.. code-block:: java
:copyable: false

77665544-3322-1100-ffee-ddccbbaa9988

To standardize GUID byte order across applications, we added ``BsonBinaryData`` subtype 4,
which all MongoDB drivers encode in the same way. If your application uses GUIDs, we
recommend using ``BsonBinaryData`` subtype 4 to store them.

For a list of all ``BsonBinaryData`` subtypes, see the
API documentation for the `BsonBinarySubType <{+new-api-root+}/MongoDB.Bson/MongoDB.Bson.BsonBinarySubType.html>`__
enum.

BsonDefaults.GuidRepresentationMode = GuidRepresentationMode.V3;
Serializing GUIDs
-----------------

Running in ``V3`` mode changes the behavior of the driver in the following ways:
Although we recommend using subtype 4 for all new ``BsonBinaryData`` GUIDs, some older
MongoDB collections might contain some GUID fields that use subtype 3 and others that use
subtype 4. To account for these differences, the {+driver-short+} handles GUID
serialization at the level of individual properties.

- The ``BsonBinaryReader.ReadBinaryData()`` method ignores ``readerSettings.GuidRepresentation``
- The ``BsonBinaryWriter.WriteBinaryData()`` method ignores ``writerSettings.GuidRepresentation``
- The ``JsonReader.ReadBinaryData()`` method ignores ``readerSettings.GuidRepresentation``
- ``JsonWriter`` ignores ``writerSettings.GuidRepresentation``
- Calling the ``BsonBinaryData.ToGuid()`` method without the ``GuidRepresentation``
parameter works only on GUIDs of subtype 4.
The {+driver-short+} uses the ``GuidRepresentation`` enum to represent the different
``BsonBinaryData`` subtypes. The following table shows the ``GuidRepresentation`` enum
members and the corresponding ``BsonBinaryData`` subtypes:

.. list-table::
:header-rows: 1
:stub-columns: 1
:widths: 10 10

* - GuidRepresentation Member
- BsonBinaryData Subtype

* - ``Standard``
- 4

* - ``CSharpLegacy``
- 3

* - ``JavaLegacy``
- 3

* - ``PythonLegacy``
- 3

* - ``Unspecified``
- N/A

.. note::

The ``CSharpLegacy``, ``JavaLegacy``, and ``PythonLegacy`` GUID representations are
all equivalent to ``BsonBinaryData`` subtype 3, but use different byte orders.

You can't use both ``GuidRepresentationMode.V2`` and ``GuidRepresentationMode.V3``
in a single application.
The following sections describe the ways in which you can configure GUID representation
in your application.

Serializing GUIDs in V3
-----------------------
Configure with Attributes
~~~~~~~~~~~~~~~~~~~~~~~~~

``GuidRepresentationMode.V3`` handles GUID serialization at the level of individual
properties. This mode is more flexible than ``V2``, but it also means you must ensure that
each GUID field is serialized and deserialized correctly.
If you're using the {+driver-short+} to
:ref:`automap your {+language+} classes to document schemas <csharp-class-mapping>`,
you can add the ``BsonGuidRepresentation`` attribute to a GUID property
to specify its representation. This attribute accepts a value from the

If you're using the {+driver-short+} to :ref:`automap your {+language+} classes to document schemas <csharp-class-mapping>`,
you can use the ``BsonGuidRepresentation`` attribute on a GUID property
to specify the representation:
The following code example specifies the ``Standard`` GUID representation for the
``G`` property:

.. code-block:: csharp

Expand All @@ -116,20 +148,16 @@ to specify the representation:
public Guid G { get; set; }
}

.. note::

``GuidRepresentation.Standard`` is equivalent to ``BsonBinaryData`` subtype 4.
Other GUID representations in the {+driver-short+}, such as ``CSharpLegacy``,
``JavaLegacy``, and ``PythonLegacy``, are equivalent to subtype 3 but use
different byte orders.
Configure in Code
~~~~~~~~~~~~~~~~~

If you're writing your own serialization code, you can use the
``GuidSerializer`` class to serialize and deserialize individual GUID values to and
from BSON fields. To ensure that the driver handles GUIDs correctly, use the
``GuidRepresentation`` parameter when you construct a ``GuidSerializer``.

The following code sample creates an instance of ``GuidSerializer``
for serializing GUID representations of subtype 4:
The following code sample creates an instance of the ``GuidSerializer`` class
for serializing properties that use ``BsonBinaryData`` subtype 4:

.. code-block::

Expand All @@ -145,18 +173,23 @@ in your application, such as during the bootstrapping phase:

.. tip::

When you're working with two subtypes, you can combine a global serializer with the
``BsonGuidRepresentation`` property attribute. For example, you can register a global
serializer for the most commonly used GUID subtype, then use the ``BsonGuidRepresentation``
attribute to denote any GUID properties of another subtype.
When you're working with two ``BsonBinaryData`` subtypes, you can combine a global
serializer with the ``BsonGuidRepresentation`` property attribute. For example, you
can register a global serializer for the most commonly used GUID subtype, then use
the ``BsonGuidRepresentation`` attribute to denote any GUID properties of another subtype.

Serializing Objects in V3
-------------------------
.. important::

If you don't globally register a serializer, you must apply the ``BsonGuidRepresentation``
attribute to every serializable GUID property. Otherwise, the driver throws an exception
when it tries to serialize the property.

Serializing Objects
-------------------

You can use an ``ObjectSerializer`` to serialize hierarchical objects to subdocuments.
To ensure that GUIDs in these objects are serialized and deserialized correctly when using
``V3``, you should select the correct GUID representation when constructing your
``ObjectSerializer``.
To ensure that GUIDs in these objects are serialized and deserialized correctly,
select the correct GUID representation when constructing your ``ObjectSerializer``.

The following code sample shows how to
create an ``ObjectSerializer`` for a GUID representation of subtype 4:
Expand Down Expand Up @@ -192,5 +225,4 @@ guide, see the following API documentation:
- `GuidRepresentationMode <{+new-api-root+}/MongoDB.Bson/MongoDB.Bson.GuidRepresentationMode.html>`__
- `BsonGuidRepresentation <{+new-api-root+}/MongoDB.Bson/MongoDB.Bson.Serialization.Attributes.BsonGuidRepresentationAttribute.html>`__
- `GuidSerializer <{+new-api-root+}/MongoDB.Bson/MongoDB.Bson.Serialization.Serializers.GuidSerializer.html>`__
- `ObjectSerializer <{+new-api-root+}/MongoDB.Bson/MongoDB.Bson.Serialization.Serializers.ObjectSerializer.html>`__

- `ObjectSerializer <{+new-api-root+}/MongoDB.Bson/MongoDB.Bson.Serialization.Serializers.ObjectSerializer.html>`__
18 changes: 18 additions & 0 deletions source/upgrade.txt
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,24 @@ Version 3.0 Potential Breaking Change
- The LINQ2 provider has been removed from this version of the driver.
You must use LINQ3 for all LINQ queries.

- Previous versions of the {+driver-short+} supported two GUID representation modes.
In version 3.0, ``GuidRepresentationMode.V3`` is the only supported mode. This change
has the following effects on the driver:

- The ``BsonBinaryData(Guid)`` constructor has been removed. To construct a ``BsonBinaryData``
object from a GUID, use the ``BsonBinaryData.Create(Guid, GuidRepresentation)`` constructor.
- The ``BsonBinaryData.GuidRepresentation`` property has been removed.
- You can call the ``BsonBinaryData.ToGuid()`` method only on ``BsonBinaryData``
objects of subtype 4. If the object has any other subtype, you must call the
``BsonBinaryData.ToGuid(GuidRepresentation)`` method and specify the subtype.

The preceding changes affect your application only if you serialize and deserialize
BSON documents directly. If you map your MongoDB documents only to :ref:`csharp-poco`,
the ``GuidRepresentationMode`` doesn't affect your application.

To learn more about serializing GUIDs in the {+driver-short+}, see the
:ref:`GUIDs <csharp-guids>` page.

.. _csharp-breaking-changes-2.28.0:

Version 2.28.0 Potential Breaking Change
Expand Down
Loading