Как я могу управлять изменением структур данных в коллекциях MongoDb с Simple.Data?

В настоящее время мы используем Simple.Data и адаптер MongoDb. Получив документ, мы добавляем его в POCO, например:

(User)db.Users.FindById(1234);

Начнем с того, что это работает довольно хорошо (черт возьми, никакой схемы!). Однако, если мы изменим структуру объекта User (например, добавим новое поле или изменим тип данных поля), то мы больше не сможем преобразовать исходный документ, поскольку он не соответствует нашей новой структуре класса.

Чтобы решить эту проблему, мы до сих пор пробовали два самых простых подхода:

  1. Обновление данных вручную для отражения изменений в структуре документа. На данный момент все в порядке, но не управляемо, когда проект развертывается в нескольких средах / запускается в производство.
  2. Ручное отображение; например. приведение SimpleRecord к словарю и оценка членов вручную. Я обеспокоен производительностью этого подхода, хотя еще не тестировал его. Меня также беспокоит, что я не нашел способа сделать его универсальным без использования отражения целевого типа для идентификации имен членов.

Мы также рассмотрели способы решения этой проблемы с помощью Ruby и Python. Первое привлекает больше (сохранение старых версий схемы в Ming кажется излишним).

Прежде чем я сбегу и портирую что-нибудь сумасшедшее, кто-нибудь решил эту проблему с помощью Simple.Data? Может ли кто-нибудь предложить какие-либо рекомендации относительно передовых методов работы с изменениями структуры документов в базах данных без схемы?


person Morgan Bruce    schedule 17.09.2011    source источник
comment
Это очень сильно зависит от сценария conrete, его нет. Вот как это делается в mongo, поэтому некоторые варианты использования были бы полезны   -  person Yurii Hohan    schedule 17.09.2011
comment
@Hohhi В основном добавляли поля или меняли типы данных, например. добавить новое поле в документ public List<Activity> Activities или изменить тип, public int SomeValue станет public string SomeValue. На данный момент есть только два разработчика, так что мы хорошо справляемся с этим, но с большим количеством разработчиков и большим количеством сборок, похоже, это вызовет головную боль. Насколько я понимаю, это либо изменение старых данных, либо отображение таким образом, чтобы игнорировать изменения данных, но я не совсем понимаю, как сделать это относительно бесшовным / уменьшить боль в среде с быстрые изменения ...   -  person Morgan Bruce    schedule 18.09.2011


Ответы (1)


Посмотри кастомную сериализацию. В моем случае это было быстро и полезно:

public class FieldsWrapper : IBsonSerializable
{
    public List<DataFieldValue> DataFieldValues { get; set; }


    public object Deserialize(MongoDB.Bson.IO.BsonReader bsonReader, Type nominalType, IBsonSerializationOptions options)
    {
    if (nominalType != typeof(FieldsWrapper)) throw new ArgumentException("Cannot deserialize anything but self");
    var doc = BsonDocument.ReadFrom(bsonReader);
    var list = new List<DataFieldValue>();
    foreach (var name in doc.Names)
    {
        var val = doc[name];
        if (val.IsString)
            list.Add(new DataFieldValue {LocalIdentifier = name, Values = new List<string> {val.AsString}});
        else if (val.IsBsonArray)
        {
            DataFieldValue df = new DataFieldValue {LocalIdentifier = name};
            foreach (var elem in val.AsBsonArray)
            {
                df.Values.Add(elem.AsString);
            }
            list.Add(df);
        }
    }
    return new FieldsWrapper {DataFieldValues = list};
    }


    public void Serialize(MongoDB.Bson.IO.BsonWriter bsonWriter, Type nominalType, IBsonSerializationOptions options)
    {
        if (nominalType != typeof (FieldsWrapper))
            throw new ArgumentException("Cannot serialize anything but self");
        bsonWriter.WriteStartDocument();
        foreach (var dataFieldValue in DataFieldValues)
        {

            bsonWriter.WriteName(dataFieldValue.LocalIdentifier);
            if (dataFieldValue.Values.Count != 1)
            {
                var list = new string[dataFieldValue.Values.Count];
                for (int i = 0; i < dataFieldValue.Values.Count; i++)
                    list[i] = dataFieldValue.Values[i];
                BsonSerializer.Serialize(bsonWriter, list); 
            }
            else
            {
                BsonSerializer.Serialize(bsonWriter, dataFieldValue.Values[0]); 
            }
        }
        bsonWriter.WriteEndDocument();
    }

}

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

person Yurii Hohan    schedule 19.09.2011