Есть ли поддержка драйверов для Mongodb C # System.Dynamic.DynamicObject в .NET 4?

17

Im работает над проектом, использующим .NET Razor и mongodb. Я хотел бы сделать что-то вроде этого:

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

Однако текущий Mongodb C # драйвер FindAll () возвращает коллекцию BsonDocument, которая не поддерживает динамический объект. Кто-нибудь знает динамический поддерживаемый драйвер .NET C ++ с поддержкой .NET 4?

Спасибо большое

    
задан hoang 19.04.2012 в 08:03
источник

5 ответов

14

В настоящее время поддержка драйверов MongoDB не поддерживается. Это связано с тем, что он основан на .NET 3.5. Однако, поскольку сборка .NET 4.0 может ссылаться на сборку .NET 3.5, вы можете написать IBsonSerializationProvider и IBsonSerializer в .NET 4.0 для поддержки динамики.

Мы, 10gen, смотрим на это в будущем. Я просил некоторую поддержку на ссылке , если вы хотите взглянуть. Есть определенно ошибки, но это показывает, что это возможно.

    
ответ дан Craig Wilson 19.04.2012 в 16:29
источник
  • Спасибо Крейгу, я нашел способ заставить его работать. здесь group.google.com/forum/?fromgroups#!topic/mongodb-user/... –  hoang 20.04.2012 в 06:46
  • Да, я это видел. Я буду эхо здесь для пользователей SO. Это прекрасно работает, но требует изменения уровня ядра. Способ, который я представил выше, является боковой нагрузкой и выполняет одно и то же без изменения ядра. Очевидно, что есть некоторые отличия, но он получает большую часть пути. В конце концов, это всего лишь шип, поэтому ... –  Craig Wilson 20.04.2012 в 18:34
  • Взгляните на MongoDB.Dynamic. Он использует официальный драйвер MongoDB и использует подход с использованием интерфейсов с динамикой C # 4.0. –  Jone Polvora 04.06.2012 в 22:49
  • Является ли это официальной частью водителя сейчас? –  jjxtra 10.07.2014 в 17:02
  • Мы все еще работаем над документацией, но поддерживаем динамику в драйвере 2.0.0 (в настоящее время в rc0): mongodb.github.io/mongo-csharp-driver/2.0/what_is_new/#new-api –  Craig Wilson 01.04.2015 в 13:43
Показать остальные комментарии
17

Я создал прямое расширение для драйвера MongoDB, который повторно сериализует документ BSON с помощью Json.NET и десериализует его как динамический. Включив следующий класс, вы можете просто преобразовать ваши запросы MongoDB в динамические, как это.

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

Класс расширения:

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

Обязательно обратитесь к Newtonsoft.Json.dll ( Ссылка )

    
ответ дан Maximilian Scherer 25.10.2012 в 09:25
источник
  • Использование bson.ToJson (новый JsonWriterSettings {OutputMode = JsonOutputMode.Strict}) устраняет необходимость во всей обработке Regex для удаления специфичных для Mongo методов Json. –  Andy McCluggage 14.01.2015 в 17:42
5

У меня есть чистое решение с использованием пользовательских IBsonSerializer и Newtonsoft.Json.

Настройте свой собственный сериализатор на BsonClassMap

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

или на свойстве

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

И просто включите следующий класс

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

    
ответ дан Rolf Wessels 23.04.2014 в 14:18
источник
  • Может ли вы привести пример о том, как обезвредить один bsondocument в динамический? –  Nati Krisi 17.02.2015 в 15:21
4

Просто чтобы ответить на вопрос Максимилиана. Это вернет список динамики из любого запроса.

    /// <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;
    }
    
ответ дан Donny V. 22.01.2013 в 16:48
источник
  • Это кажется излишним. Вы можете просто сделать курсор. Выберите (doc => doc.ToDynamic ()). Добавьте .ToList (), если необходимо. В общем, следует избегать методов записи, для которых структура уже обеспечивает хорошее решение. –  Tomas 25.03.2013 в 16:23
0

Несмотря на то, что это старая тема, она по-прежнему так же актуальна сегодня, как и когда была сделана запись, и мне еще предстоит увидеть какие-либо решения там, которые предоставляют простое решение для двухсторонней поддержки, я изменил код @Maximilian Scherer, что он позволяет конвертировать в динамические объекты, которые легко позволяют вам сохранить документ снова.

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

Пример использования:

// 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));
    
ответ дан Joachim 31.07.2015 в 02:46
источник