覆盖Json序列化RavenDB

时间:2014-09-30 14:46:55

标签: c# json serialization ravendb

我正在尝试使用RavenDB。我们有大量的实体对象,它们按照以下(简单)示例用属性进行修饰:

[Entity(UniqueID = "37AA8322-597D-48E8-BB66-7B2796103D95")]
public class SampleEntity : Entity
{
    protected SampleEntity()
    {

    }

    public static SampleEntity Create()
    {
        return EntityFactory.Create<SampleEntity>();
    }

    [Property]
    public virtual int Integer { get; set; }
}

EntityFactory发出的类型实际上是SampleEntity的一个子类,它覆盖自动实现INotifyPropertyChanged的setter / getter,并跟踪每个属性的上次修改时间(以及其他内容)。

使用Json.NET我为实体提供了一个Json序列化程序,对于SampleEntity和&#39; Integer&#39;设置为8会吐出类似于以下内容的内容:

{
  "TypeID": "\"37aa8322-597d-48e8-bb66-7b2796103d95\"",
  "UniqueID": "\"e1f03e21-260f-4bde-8bfb-ec7a47b2e379\"",
  "Integer": {
    "Last Set": "2014-09-30T14:06:08.9146417Z",
    "Value": "8"
  }
}

注意&#39;整数&#39;财产扩大到包括&#39;价值&#39;和&#39;最后一组&#39;如果我要求RavenDB存储SampleEntity,我(如预期的那样)不会得到“最后一组”&#39;符合&#39;价值&#39; (在基类中有一个字典映射属性名称到有关属性的信息,一个字段是最后一次设置属性时)。

理想情况下,我想存储我在RavenDB中编写的Json-Entity序列化程序的输出(具有为每个实体自动生成的UniqueID作为文档ID)。当我检索文档时,它将是原始json,我将负责使用它来水合适当的实体对象。我已经进行了广泛的搜索,找不到一种简单的方法来实现这一点,这在历史上意味着我试图做一些愚蠢的事情。

我是RavenDB(一般文档数据库)和Json的新手,所以也许我试图在这里将一个方形钉子塞进一个圆孔中,并且有一种更优雅的方式来处理这种情况。

有人知道在RavenDB中存储原始json的方法吗?或者对我可以完成我所描述的其他方式有任何意见/建议吗?

2 个答案:

答案 0 :(得分:1)

一种选择是使用转换器来自定义写入数据库的RavenJObject,并自定义填充所需返回对象的方式。

下面是一些代码:

public class SampleEntityConverter : IDocumentConversionListener
{
    public void EntityToDocument(string key, object entity, RavenJObject document, RavenJObject metadata)
    {
        var obj = entity as SampleEntity;
        if (obj == null)
        {
            return;
        }

        var integer = new RavenJObject();
        integer["Last Set"] = obj.HoweverYouGetTheLastSetDateTime;
        integer["Value"] = obj.Integer;
        document["Integer"] = integer;
    }

    public void DocumentToEntity(string key, object entity, RavenJObject document, RavenJObject metadata)
    {
        var obj = entity as SampleEntity;
        if (obj == null)
        {
            return;
        }

        var integer = document["Integer"] as RavenJObject;       
        if (integer != null && integer.ContainsKey("Value"))
        {
            obj.Integer = integer["Value"];
        }
    }
}

然后在DocumentStore实例上注册它:

documentStore.RegisterListener(new SampleEntityConverter());

答案 1 :(得分:1)

您可以使用RavenDB使用的JSON.Net的内部副本注册相同的转换器。 在约定中,查看CustomizeSerialize方法