我如何管理在MongoDb集合w/ Simple.Data不断变化的数据结构



我们目前使用的是Simple。数据和MongoDb适配器。当检索到文档时,将其强制转换为POCO,例如:

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

首先,这工作得很好(见鬼,没有模式!)。但是,如果我们改变User对象的结构(例如,添加一个新字段,或者改变字段的数据类型),那么我们就不能再强制转换原始文档,因为它与我们的新类结构不匹配。

为了解决这个问题,我们已经尝试了两种最直接的方法:
  1. 手动更新数据以反映文档结构的变化。目前还可以,但当项目部署在多个环境中/使其进入生产环境时,就无法管理了
  2. 手动映射;如。将SimpleRecord转换为字典并手动计算成员。我很关心这种方法的性能,尽管还没有对它进行基准测试。我还担心,我还没有找到一种方法,使其通用而不使用对目标类型的反射来识别成员名称。

我们还研究了用Ruby和Python解决这个问题的方法。前者更有吸引力(在Ming中维护旧的模式版本似乎有些矫枉过正)。

在我跑去移植一些疯狂的东西之前,有人用Simple.Data解决了这个问题吗?有没有人能提供一些关于在无模式数据库中处理文档结构变化的最佳实践的指导?

查看自定义序列化。在我的例子中,它既快速又有用:

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();
    }
}
有一些其他的策略,但这似乎是最适用于你的情况。我们在生产中测试了字典,它们和其他东西一样快,如果字典不适合你的领域,你只会在映射上浪费时间,我会选择自定义序列化。

相关内容

  • 没有找到相关文章

最新更新