【问题标题】:How can I read a type name from a DocumentDB document model from within a generic DocumentDBRepository?如何从通用 DocumentDBRepository 中的 DocumentDB 文档模型中读取类型名称?
【发布时间】:2015-08-27 03:23:10
【问题描述】:

我有一个包含异构文档类型的 DocumentDB 集合。我的 DocumentDB 存储库基于this GitHub project,并具有GetItems 方法如下:

    public IReadOnlyCollection<T> GetItems()
    {
        return Client.CreateDocumentQuery<T>(Collection.DocumentsLink).ToList();
    }

    public T GetItem(Expression<Func<T, bool>> predicate)
    {
        return Client.CreateDocumentQuery<T>(Collection.DocumentsLink)
            .Where(predicate)
            .AsEnumerable()
            .FirstOrDefault();
    }

存储库运行良好,但是当我真正想按类型查询时,使用上述查询会返回我的所有文档。

几个来源(例如this redditthis SO question)建议使用内置在我的DocumentModels 中的类型属性,因此我更新了我的BaseDocument 类(所有文档都继承自该类)以包含一个类型。 BaseDocument 现在看起来像这样:

[Serializable]
public class BaseDocument
{
    [JsonProperty(PropertyName = "id")]
    public string Id { get; set; }

    [JsonProperty(PropertyName = "type")]
    public string Type { get; set; }

    public BaseDocument(string id, string type)
    {
        Id = id;
        Type = type;
    }
}

我已尝试更改我的 GetItems 方法以包含类型字符串,如下所示:

public IReadOnlyCollection<T> GetItems(string type)
{    
    return Client.CreateDocumentQuery<T>(Collection.DocumentsLink,
        String.Format("SELECT * FROM collection c WHERE c.type = '{0}'", type)).ToList();
}

这可行,但每次调用GetItems() 时都必须通过魔术字符串似乎很笨拙。我想我可以在每个FooDocument(每个都扩展BaseDocument)中包含一个常量来指定类型名称,但我不知道如何在不通过它的情况下阅读它。我如何从 DocumentDbRepository&lt;FooDocument&gt; 类中读取此常量?

【问题讨论】:

    标签: c# azure generics repository azure-cosmosdb


    【解决方案1】:

    向返回类型的 BaseDocument 添加公共 get 属性 类似的东西(这里是伪代码,请多多包涵);

    public string Type
        get {
            return this.GetType() // you can control if you want the FQN or just the name
        }
    

    将以下内容添加到 GetItems 方法签名的末尾

    where T : BaseDocument
    

    现在你可以在你的 repo 中做这样的事情了;

        return Client.CreateDocumentQuery<T>(Collection.DocumentsLink,
        String.Format("SELECT * FROM collection c WHERE c.type = '{0}'", T.Type)).ToList();
    

    这消除了对常量的需求,并且您不必将类型作为参数传递给您的方法。

    您甚至可以使用 LINQ 执行以下操作;

    GetItems<T>(Predicate predicate) Where T : BaseDocument {
        return client.CreateDocumentQuery(collectionLink)
                    .Where(predicate)
                    .Where(d => d.Type == T.Type);
    }
    

    如果您希望我可以在某处分享/发布,我有一个工作存储库可以执行此操作。

    【讨论】:

    • 谢谢!我想我可以从您的回答中解决这个问题,但是如果您可以添加指向 github 项目或其他内容的链接,那就太好了!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-27
    • 2019-05-26
    • 2013-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多