2012-04-19 5 views
17

Ich arbeite an einem Projekt, das .NET Razor und Mongodb verwendet. Ich möchte so etwas wie dies tun:Gibt es mongodb C# -Treiberunterstützung System.Dynamic.DynamicObject in .NET 4?

@{ 
    var feeds = DP.Database.GetCollection("feeds").FindAll(); 
} 
<ul> 
    @foreach (dynamic feed in feeds) 
    { 
     <li>@feed.message - @feed.from.name</li> 
    } 
</ul> 

Doch die aktuelle # Treiber FindAll mongodb C() return Sammlung von BsonDocument, die nicht unterstützt dynamisches Objekt. Kennt jemand einen .NET 4 dynamisch unterstützten mongodb C# -Treiber?

Vielen Dank

Antwort

14

Derzeit gibt es keine Unterstützung für die Dynamik im MongoDB-Treiber. Dies liegt daran, dass es auf .NET 3.5 basiert. Da eine .NET 4.0-Assembly jedoch auf eine .NET 3.5-Assembly verweisen kann, können Sie in .NET 4.0 einen IBsonSerializationProvider und einen IBsonSerializer zur Unterstützung der Dynamik schreiben.

Wir, 10gen, schauen uns das in Zukunft an. Ich habe Unterstützung bei https://github.com/craiggwilson/mongo-csharp-driver/tree/dynamic gespickt, wenn Sie einen Blick darauf werfen möchten. Es gibt definitiv Fehler, aber es zeigt, dass es möglich ist.

+0

Dank Craig, fand ich einen Weg, es funktioniert. Check here https://groups.google.com/forum/?fromgroups#!topic/mongodb-user/AEIfBP9IWQw – hoang

+1

Ja, das habe ich gesehen. Ich werde hier für SO Benutzer Echo. Das funktioniert gut, erfordert aber eine geringe Änderung des Kerns.Die Art und Weise, wie ich oben dargestellt habe, ist eine Seitenlast und führt das gleiche aus, ohne den Kern zu verändern. Offensichtlich gibt es einige Unterschiede, aber es kommt den meisten Weg dorthin. Es ist nur ein Spike, also ... –

+1

Werfen Sie einen Blick auf [MongoDB.Dynamic] (http://www.assembla.com/spaces/mongodb-dynamic/wiki). Es verwendet den offiziellen Treiber von MongoDB und verwendet einen Ansatz zur Verwendung von Schnittstellen mit der Dynamik von C# 4.0. –

16

Ich habe eine direkte Erweiterung des MongoDB-Treibers erstellt, der das BSON-Dokument unter Verwendung von Json.NET erneut serialisiert und es als dynamischen Eintrag deserialisiert. Durch die Einbeziehung der folgenden Klasse, können Sie einfach Ihre MongoDB-Abfragen dynamisch konvertieren wie diese

dynamic obj = collection.FindOneByIdAs<BsonDocument>(someObjectId).ToDynamic(); 

Erweiterungsklasse:

public static class MongoDynamic 
{ 
    private static System.Text.RegularExpressions.Regex objectIdReplace = new System.Text.RegularExpressions.Regex(@"ObjectId\((.[a-f0-9]{24}.)\)", System.Text.RegularExpressions.RegexOptions.Compiled); 
    /// <summary> 
    /// deserializes this bson doc to a .net dynamic object 
    /// </summary> 
    /// <param name="bson">bson doc to convert to dynamic</param> 
    public static dynamic ToDynamic(this BsonDocument bson) 
    { 
     var json = objectIdReplace.Replace(bson.ToJson(), (s) => s.Groups[1].Value); 
     return Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json); 
    } 
} 

Seien Sie sicher, Newtonsoft.Json.dll (http://james.newtonking.com/projects/json-net.aspx)

+1

Mit 'bson.ToJson (new JsonWriterSettings {OutputMode = JsonOutputMode.Strict})' entfällt die Notwendigkeit, dass alle Regex-Prozesse Mongo-spezifische Json-Methoden entfernen. –

4

referenzieren Nur um auf Maximilians Antwort aufzubauen. Dies gibt eine Liste der Dynamiken von jeder Abfrage zurück.

/// <summary> 
    /// deserializes this BsonDocument cursor result to a list of .net dynamic objects 
    /// </summary> 
    /// <param name="cursor">cursor result to convert to dynamic</param> 
    /// <returns></returns> 
    public static List<dynamic> ToDynamicList(this MongoCursor<BsonDocument> cursor) 
    { 
     var dynamicList = new List<dynamic>(); 
     var list = cursor.ToList(); 
     for (int i = 0, l = list.Count; i < l; i++) 
      dynamicList.Add(list[i].ToDynamic()); 

     return dynamicList; 
    } 
+2

Dies scheint überflüssig. Sie könnten einfach 'cursor.Wählen (doc => doc.ToDynamic())'. Fügen Sie '.ToList()' bei Bedarf hinzu. Im Allgemeinen sollten Schreibmethoden, für die das Framework bereits eine gute Lösung bietet, vermieden werden. – Tomas

5

Ich habe eine saubere Lösung mit benutzerdefinierten IBsonSerializer und Newtonsoft.Json.

Richten Sie Ihre individuelle Serializer auf der BsonClassMap

map.MapProperty(member => member.Data) 
    .SetElementName("Data") 
    .SetSerializer(new DynamicSerializer()); 

oder auf dem Grundstück

[BsonSerializer(typeof(DynamicSerializer))] 
public dynamic Data { get; set; } 

Und sind nur die folgenden Klasse

public class DynamicSerializer : IBsonSerializer 
{ 
    #region Implementation of IBsonSerializer 

    public object Deserialize(BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options) 
    { 
    return Deserialize(bsonReader, nominalType, null, options); 
    } 

    public object Deserialize(BsonReader bsonReader, Type nominalType, Type actualType, 
    IBsonSerializationOptions options) 
    { 
    if (bsonReader.GetCurrentBsonType() != BsonType.Document) throw new Exception("Not document"); 
    var bsonDocument = BsonSerializer.Deserialize(bsonReader, typeof(BsonDocument), options) as BsonDocument; 
    return JsonConvert.DeserializeObject<dynamic>(bsonDocument.ToJson()); 
    } 

    public IBsonSerializationOptions GetDefaultSerializationOptions() 
    { 
    return new DocumentSerializationOptions(); 
    } 

    public void Serialize(BsonWriter bsonWriter, Type nominalType, object value, IBsonSerializationOptions options) 
    { 
    var json = (value == null) ? "{}": JsonConvert.SerializeObject(value); 
    BsonDocument document = BsonDocument.Parse(json); 
    BsonSerializer.Serialize(bsonWriter, typeof(BsonDocument), document,options); 
    } 

    #endregion 
} 

InfoSlips - GlobalKinetic

+1

Kannst du Beispiel geben, wie man ein einzelnes bsondocument in dynamic deserilze? –

0

Obwohl dies ein altes Thema ist, das heute immer noch genauso relevant ist, wie wenn es veröffentlicht wurde, und ich noch keine Lösungen für eine einfache Lösung für die Zweiwege-Unterstützung gefunden habe, habe ich @Maximilian Scherer Code so geändert, dass es funktioniert können Sie in dynamische Objekte konvertieren, mit denen Sie Ihr Dokument einfach erneut speichern können.

public static class MongoDynamic 
{ 
    /// <summary> 
    /// deserializes this bson doc to a .net dynamic object 
    /// </summary> 
    /// <param name="bson">bson doc to convert to dynamic</param> 
    public static dynamic ToDynamic(this BsonDocument bson) 
    { 
     var json = bson.ToJson(new MongoDB.Bson.IO.JsonWriterSettings { OutputMode = JsonOutputMode.Strict }); 
     dynamic e = Newtonsoft.Json.JsonConvert.DeserializeObject<ExpandoObject>(json); 
     BsonValue id; 
     if (bson.TryGetValue("_id", out id)) 
     { 
      // Lets set _id again so that its possible to save document. 
      e._id = new ObjectId(id.ToString()); 
     } 
     return e; 
    } 
} 

Anwendungsbeispiel:

// Get BsonDocument from db here 
BsonDocument doc = ... 

// Convert to dynamic. 
var d = doc.ToDynamic(); 

// Lets add a none existant property. 
d.Name = "test"; 

// Assuming you already have your collection set up 
collection.Save(new BsonDocument(d)); 
Verwandte Themen