Как мне управлять изменяющимися структурами данных в коллекциях MongoDb с Simple.Data? - PullRequest
3 голосов
/ 17 сентября 2011

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

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

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

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

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

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

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

1 Ответ

2 голосов
/ 20 сентября 2011

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

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

}

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

...