简体   繁体   中英

How to convert a BsonDocument into a strongly typed object with the official MongoDB C# driver?

For unit testing purposes, I'd like to test my class mappings without reading and writing documents into the MongoDB database. To handle special cases such as circular parent / child references and read only properties, I've used BsoncClassMap.RegisterClassMap< MyType>(...) with some custom mappings overriding the default AutoMap(); generated mappings.

Does anyone know how to convert a BsonDocument into the desired strongly typed object without making a round trip to the database? The driver is doing this when going to and from the data store. My goal would be to use the same logic that the MongoDB C# driver is using internally to test the serialization to / from a C# domain object into a BsonDocument.

I'm able to use the Bson extension method ToBsonDocument() to convert a C# object into a BsonDocument? The piece that I'm lacking is the reverse of the process - essentially a BsonDocument.ToObject< MyType>(); .

Is this possible with the latest version of the official MongoDB C# driver? It seems like it should be - I'm wondering if I'm just blind and am missing the obvious.

The MongoDB Driver does provide a method for deserializing from Bson to your type. The BsonSerializer can be found in MongoDB.Bson.dll , in the MongoDB.Bson.Serialization namespace.

You can use the BsonSerializer.Deserialize<T>() method. Some example code would be

var obj = new MyClass { MyVersion = new Version(1,0,0,0) };
var bsonObject = obj.ToBsonDocument();
var myObj = BsonSerializer.Deserialize<MyClass>(bsonObject);
Console.WriteLine(myObj);

Where MyClass is defined as

public class MyClass
{
    public Version MyVersion {get; set;}
}

I hope this helps.

A straight forward way if you want to map rows fetched from mongoDB to a class within your code is as below

//Connect and Query from MongoDB
var db = client.GetDatabase("blog");
var col = db.GetCollection<BsonDocument>("users");
var result = await col.Find(new BsonDocument("Email",model.Email)).ToListAsync();

//read first row from the result
var user1 = result[0];
result[0] would be say "{ "_id" : ObjectId("569c05da09f251fb0ee33f5f"), "Name" : "fKfKWCc", "Email" : "pujkvBFU@kQKeYnabk.com" }"

//A user class with name and email
User user = new User();

// assign 
User.Name = user1[1].ToString();      // user1[1] is "fKfKWCc"    
User.Email = user1[2].ToString();      // user1[2] is "pujkvBFU@kQKeYnabk.com"

In case of you need a part of object, for example: You have entity Teacher:

public class Teacher
{
public string Mail {get; set;}
public IEnumerable<Course> Courses {get; set;}
public string Name {get; set;}
}

And entity Course:

public class Course
{
public int CurseCode {get; set;}
public string CourseName {get; set;}
}

And you need only "Courses" from "Teacher" entity, you can use:

var db = conection.GetDatabase("school");
var collection = db.GetCollection<Teacher>("teachers"); // Or your collection Name
string mailForSearch="teacher@school.com"; // param for search in linq
var allCoursesBson = collection.Find(x => x.Mail == mailForSearch).Project(Builders<Teacher>.Projection.Include(x => x.Courses).Exclude("_Id")).ToList();
// allCoursesBson is BsonDocument list, then use a first BsonDocument an convert to string for convert to IEnumerable<Courses> type with  BsonSerializer.Deserialize
string allCoursesText = resp.FirstOrDefault()[0].ToString();
IEnumerable<Courses> allCourses = BsonSerializer.Deserialize<IEnumerable<Courses>>(allCoursesText);

Now, you have a courses list from taecher and convert BsonDocument answer into "IEnumerable".

Use yield keyword to return data as you want.

public IEnumerable<string> GetMongoFields(string collectionName)
        {
            var connectionString = ConfigurationManager.ConnectionStrings[DbConfig.GetMongoDb()].ConnectionString;
            var databaseName = MongoUrl.Create(connectionString).DatabaseName;
            MongoClient client = new MongoClient(connectionString);
            var server = client.GetServer();
            var db = server.GetDatabase(databaseName);

            var collection = db.GetCollection<BsonDocument>(collectionName);
            var list = collection.FindAll().ToList();

           yield return list.ToJson();
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM