2012-04-19 12 views
17

Im trabajando en un proyecto que usa .NET Razor y mongodb. Me gustaría hacer algo como esto:¿Hay compatibilidad con el controlador mongodb C# System.Dynamic.DynamicObject en .NET 4?

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

Sin embargo, la colección de retorno de corriente mongodb C# conductor FindAll() de BsonDocument que no soporta objeto dinámico. ¿Alguien sabe un .NET 4 dynamic supported mongodb C# driver?

Muchas gracias

Respuesta

14

la actualidad, no hay soporte para el conductor dinámico en MongoDB. Esto se debe a que está basado en .NET 3.5. Sin embargo, dado que un ensamblado de .NET 4.0 puede hacer referencia a un ensamblado de .NET 3.5, es posible escribir un IBsonSerializationProvider y un IBsonSerializer en .NET 4.0 para admitir dinámicas.

Nosotros, 10gen, estamos buscando hacer esto en el futuro. He agregado un poco de soporte al https://github.com/craiggwilson/mongo-csharp-driver/tree/dynamic si quieres echarle un vistazo. Definitivamente hay errores, pero muestra que es posible.

+0

Gracias Craig, he encontrado una manera de hacer que funcione. mira aquí https://groups.google.com/forum/?fromgroups#!topic/mongodb-user/AEIfBP9IWQw – hoang

+1

Sí, lo vi. Voy a hacer un eco aquí para los usuarios de SO. Eso funciona bien, pero requiere una modificación de bajo nivel en el núcleo.La forma que presenté arriba es una carga lateral y logra lo mismo sin modificar el núcleo. Obviamente, hay algunas diferencias, pero se lleva la mayor parte del camino hasta allí. Es solo un pico después de todo, así que ... –

+1

Eche un vistazo a [MongoDB.Dynamic] (http://www.assembla.com/spaces/mongodb-dynamic/wiki). Utiliza el controlador oficial de MongoDB y adopta un enfoque de uso de interfaces con la dinámica de C# 4.0. –

16

Creé una extensión directa para el controlador MongoDB que serializa el documento BSON utilizando Json.NET y lo deserializa como una dinámica. Con la inclusión de la siguiente clase, sólo tiene que convertir sus consultas MongoDB a dinámica como esta clase

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

Extensión:

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); 
    } 
} 

asegúrese de hacer referencia Newtonsoft.Json.dll (http://james.newtonking.com/projects/json-net.aspx)

+1

Usando 'bson.ToJson (new JsonWriterSettings {OutputMode = JsonOutputMode.Strict})' elimina la necesidad de todo el procesamiento Regex para eliminar los métodos Json específicos de Mongo. –

4

Solo para construir sobre la respuesta de Maximiliano. Esto devolverá una lista de dinámicas de cualquier consulta.

/// <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

Esto parece redundante. Simplemente podría hacer 'cursor.Select (doc => doc.ToDynamic())'. Agregue '.ToList()' si es necesario. En general, se deben evitar los métodos de escritura para los cuales el marco ya ofrece una buena solución. – Tomas

5

Tengo una solución limpia utilizando el servicio personalizado IBsonSerializer y Newtonsoft.Json.

Configuración de su serializador personalizado en el BsonClassMap

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

o en la propiedad

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

Y basta con incluir la siguiente clase

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

¿puedes dar un ejemplo sobre cómo deserilizar un único documento bson en dinámico? –

0

Aunque este es un tema antiguo, sigue siendo tan relevante hoy como cuando se realizó la publicación, y todavía no he visto ninguna solución que proporcione una solución simple para soporte bidireccional, he modificado el código @Maximilian Scherer para que le permite convertir objetos dinámicos que le permiten guardar su documento fácilmente.

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; 
    } 
} 

Ejemplo de uso:

// 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)); 
Cuestiones relacionadas