Rishabh Nigam
Rishabh Nigam

Reputation: 35

MongoDB throws exception when the Modal has Dynamic field

I am trying to migrate my Database from Cosmos to Mongo. When trying to add an entry for an object which has a C# dynamic Type in MongoDB exception is thrown from the API InsertOneAsync() provided by MongoDB.Driver.IMongoCollection Dynamic Type used to work in Cosmos DB.

MongoDB Insertion Code: _collection.InsertOneAsync(document);

Model:

namespace Entities.Models
{
    [BsonIgnoreExtraElements]
    public class UPModel
    {
        [JsonProperty(PropertyName = "_id")]
        [BsonId]
        [BsonRepresentation(BsonType.ObjectId)]
        public string BsonId { get; set; } = string.Empty;

        [BsonElement("resource")]
        public Resource Resource{ get; set; }

        [BsonElement("preference")]
        public Preference Preference { get; set; }
    }

    [BsonIgnoreExtraElements]
    public class Resource
    {
        [BsonElement("id")]
        public string Id { get; set; }

        [BsonElement("identifiers")]
        public dynamic Identifiers { get; set; }
    }

    [BsonIgnoreExtraElements]
    public class Preference
    {
        [BsonElement("id")]
        public string Id { get; set; }

        [BsonElement("value")]
        public dynamic Value { get; set; }
    }
}

Document that needs to be created for this model in the DB:

{
    "id":"uniqueIdentifier",
    "preference": {
        "id": "dummyPreferenceId",
        "value": {
            "favorites": [
                "dummyFavorites1"
            ]
        }
    },
    "resource": {
        "identifiers": {
            "userId": 99,
            "routeUrl": "dummyRouteURL",
            "type": "standard"
        },
        "id": "dummyResourceId"
    }
}

Exception:

MongoDB.Bson.BsonSerializationException
  HResult=0x80131500
  Message=An error occurred while serializing the Resource property of class UPModel: An error occurred while serializing the Identifiers property of class Resource: Type Newtonsoft.Json.Linq.JObject is not configured as a type that is allowed to be serialized for this instance of ObjectSerializer.
  Source=MongoDB.Bson
  StackTrace: "Removed for Readability"
Inner Exception 1:
BsonSerializationException: An error occurred while serializing the Resource property of class UPModel: An error occurred while serializing the Identifiers property of class Resource: Type Newtonsoft.Json.Linq.JObject is not configured as a type that is allowed to be serialized for this instance of ObjectSerializer.

Inner Exception 2:
BsonSerializationException: An error occurred while serializing the Identifiers property of class Resource: Type Newtonsoft.Json.Linq.JObject is not configured as a type that is allowed to be serialized for this instance of ObjectSerializer.

Inner Exception 3:
BsonSerializationException: Type Newtonsoft.Json.Linq.JObject is not configured as a type that is allowed to be serialized for this instance of ObjectSerializer.

I am looking for a way to save the dynamic object type of C# in MongoDB

Upvotes: 1

Views: 76

Answers (1)

Balaji
Balaji

Reputation: 1795

MongoDB throws exception when the Modal has Dynamic field

It throws an exception because MongoDB.Driver does not support Newtonsoft.Json.Linq.JObject. In your code the dynamic type in Resource.Identifiers and Preference.Value is being assigned a JObject, which MongoDB cannot serialize.

I tried with the below code, it successfully saves the dynamic object type of C# in MongoDB as shown in the output below. The code consists of two dynamic fields BsonArray and BsonDocument. Here, BsonDocument which is directly compatible with MongoDB.

static async Task Main(string[] args)
    {
        try
        {
            var connectionString = "*****";
            var settings = MongoClientSettings.FromUrl(new MongoUrl(connectionString));
            settings.ServerSelectionTimeout = TimeSpan.FromSeconds(60); 
            settings.ConnectTimeout = TimeSpan.FromSeconds(30); 

            var client = new MongoClient(settings);
            var database = client.GetDatabase("db1");

            var collectionNames = await database.ListCollectionNames().ToListAsync();
            if (!collectionNames.Contains("coll1"))
            {
                await database.CreateCollectionAsync("coll1");
                Console.WriteLine("Collection 'coll1' created.");
            }

            var collection = database.GetCollection<BsonDocument>("coll1");

            var dynamicData = new BsonDocument
            {
                { "id", "uniqueIdentifier" },
                { "preference", new BsonDocument
                    {
                        { "id", "dummyPreferenceId" },
                        { "value", new BsonDocument
                            {
                                { "favorites", new BsonArray { "dummyFavorites1" } }
                            }
                        }
                    }
                },
                { "resource", new BsonDocument
                    {
                        { "id", "dummyResourceId" },
                        { "identifiers", new BsonDocument
                            {
                                { "userId", 99 },
                                { "routeUrl", "dummyRouteURL" },
                                { "type", "standard" }
                            }
                        }
                    }
                }
            };

            await collection.InsertOneAsync(dynamicData);
            Console.WriteLine("Data inserted successfully!");

            var count = await collection.CountDocumentsAsync(FilterDefinition<BsonDocument>.Empty);
            Console.WriteLine($"Total documents in 'coll1': {count}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }
    }

Output:

Data inserted successfully!
Total documents in 'coll1': 1

Upvotes: 0

Related Questions