【问题标题】:CreateDocumentQuery does not bind to CLR objectCreateDocumentQuery 不绑定到 CLR 对象
【发布时间】:2015-09-06 19:23:47
【问题描述】:

我有一个解决方案,问题是为什么会发生这种情况以及这是否是一个好的解决方案。 背景: 在 Azure DocumentDb 中,我有一个托管哈希将一个数据库分区为一个集合。 CLR 对象继承自 Document 类。我已将 JsonProperty-attribute 放在所有属性上。

不起作用的查询是这个:

var a = _client.CreateDocumentQuery<T>(_database.SelfLink)
                .Where(d => d.Id == id)
                .AsEnumerable()
                .FirstOrDefault();

它总是返回 null (并且文档在那里,我在门户中看到它)。我现在浪费了这么多时间,我能做的就是:

var a = _client.CreateDocumentQuery<Document>(_database.SelfLink, "SELECT * FROM c")
                    .AsEnumerable().Where(t => t.Id == id)
                    .FirstOrDefault();
var obj = JsonConvert.SerializeObject(b);
T parsed = JsonConvert.DeserializeObject<T>(obj);

这不是有多可怕吗? 有谁知道为什么框架没有为我反序列化它,以及为什么它在第一个示例中找不到任何东西?

更新:

实际上,上面的“解决方案”并没有反序列化所有属性.. 我有一个属性 Dictionary&lt;Guid,Dictionary&lt;string, string&gt;&gt; 不会反序列化到 CLR 属性中。根据智能感知,该对象属于 CLR 类型,但它有很多基类信息。虽然它似乎嵌套在永恒中。无法真正看到类型是什么,但 6 级(我认为它是 Resource 基类)我找到了一个私有 _propertybag,其中所有属性为 JTokens/JProperties(老实说,我不知道如何判断它们是哪一个) . 所以,那里有 json 数据,而我需要的数据在实际对象中,它只是没有绑定到属性。 我尝试在 Resource 类上使用 .SetProperty() 方法,并且确实有效。但这应该在从 DocumentClient 获取时进行反序列化和绑定,不是吗? 我在这里做错了什么?

2 个月后: 我再次对此进行了调查,结果发现,对于我的代码中的一个地方,上述可怕的解决方法仍然是唯一可以获取我的文档的方法。原因可以在链条的早期找到。该方法的参数是Expression&lt;Func&lt;TEntity,bool&gt;&gt;。 我的调用链是

public T CreateIfNotExists<T>(Guid id) where T : IBaseDocument
{
    var id = ProduceDocId(typeof(T), id);
    var result = _repository.GetSingle<T>(r => r.Id == id);
    ...
}

然后

public T GetSingle<T>(Expression<Func<T, bool>> predicate) where T : IBaseDocument
    {
        ... // error handling ommitted
        T res = _client.CreateDocumentQuery<T>(_database.SelfLink)
            .Where(predicate)
            .AsEnumerable()
            .FirstOrDefault();
        return res;
    }

参数“谓词”将评估为匿名方法闭包,即在调试器中显示为“c__DisplayClass2”(explanation for name by Eric Lippert)。 像这样:

{s => (Convert(s).Id == value(FooNameSpace.BarClass+<>c__DisplayClass2`1[FooNameSpace.FooClass]).someId)}

documentdb 没有正确评估它,它总是返回 null。 如果我采用匿名方法闭包计算的实际 id 并改为传递,这会给我文档。

【问题讨论】:

    标签: c# .net azure deserialization azure-cosmosdb


    【解决方案1】:

    解决了!非常非常简单的答案,这完全是由于我的无知和缺乏正确的研究努力(因为伙计,我已经付出了努力..)。

    待定文档上的属性设置器不能不可访问,即私有或受保护是不行的。

    就是这样。

    2 个月后: 其实,不是这样。请参阅原始问题的最后一部分。

    【讨论】:

    • 非常感谢您的研究和辛勤工作。使我免于将头撞到墙上。谢谢!
    【解决方案2】:

    您不需要反序列化从 DocumentDB 读取文档。 像这样的函数应该为你做(这个函数中的类名与你的不同):

    public List<Candidate> GetCandidateById(int candidateId)
    {
        var client = new DocumentClient(new Uri(EndpointUrl), AuthorizationKey);
        Database database = client.CreateDatabaseQuery().Where(db => db.Id == DatabaseName).AsEnumerable().FirstOrDefault();
        DocumentCollection documentCollection = client.CreateDocumentCollectionQuery(database.CollectionsLink).Where(db => db.Id == DocumentCollectionName).AsEnumerable().FirstOrDefault();
    
        return client.CreateDocumentQuery<Candidate>(documentCollection.DocumentsLink).Where(m => m.CandidateId == candidateId).Select(m => m).ToList();
    }
    

    我在此处发布了 DocumentDB 的示例:

    http://koukia.ca/post/azure-documentdb-vs-sql-azure,-a-performance-comparison

    【讨论】:

    • 问题是我有一个托管的散列分区数据库,这意味着我无法搜索集合链接或文档链接,因为文档根据“PartitionKeySource”属性计算的散列分布在集合中因此,我对所有这些对象都有。所以在这种情况下不能使用上面的建议。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    • 2011-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    相关资源
    最近更新 更多