如何在 RavenDB 中使用引用类型作为文档中的键 [英] How to use a reference type as a key in a document in RavenDB

查看:60
本文介绍了如何在 RavenDB 中使用引用类型作为文档中的键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类要用于 RavenDB 中的文档键:

I have a class that I want to use for a document key in RavenDB:

public class DocumentKey
{
    public string Namespace { get; set; }
    public string Id { get; set; }
}

我还实现了 ITypeConverter(不是 .NET 的,RavenDB 特定的)接口来从引用类型转换为字符串(因为在数据库中,键实际上只是字符串.

I've also implemented the ITypeConverter (not the .NET one, the RavenDB-specific one) interface to convert from the reference type to a string (because in the database, the keys are all really just strings).

最后,我通过公开的ListITypeConverter的实现添加到IDocumentStore的实现中Conventions.IdentityProviders 属性.

Finally, I've added the implementation of ITypeConverter to the IDocumentStore implementation through the List<ITypeConverter> exposed through the Conventions.IdentityProviders property.

但是,IAsyncDocumentSession 实现上的 LoadAsync 重载上的签名看起来像这样(为了简洁起见,删除了采用多个 id 的签名.此外,相同的作为 IDocumentSession 接口上的 Load):

However, the signature on the LoadAsync<T> overloads on the IAsyncDocumentSession implementation look like this (removed the signatures which take multiple ids for brevity. Also, the same as Load on the IDocumentSession interface):

LoadAsync<T>(string id);
LoadAsync<T>(ValueType id);

我真的不想为我的键使用值类型,原因如下:

I really don't want to use value types for my keys for the following reasons:

  • 我有一个对密钥类型没有限制的抽象.创建单独的结构来反映这一点只是为了拥有值类型非常不方便.
  • 由于被限制为值类型,我无法完全控制类型.值类型有一个默认构造函数,它以一种我不想在代码中的其他任何地方处理的方式默认值.

如何在 RavenDB 中使用引用类型作为文档键?

How can I use a reference type as a document key in RavenDB?

推荐答案

因为在 RavenDB 中所有文档标识符最终都以字符串的形式存储,所以关键是使用了带字符串的重载:

Because all document identifiers are stored ultimately stored as strings in RavenDB, the key is using the overload that takes a string:

LoadAsync<T>(string id);

IAsyncDocumentSession 接口,您可以使用 Conventions(由 Advanced.DocumentStore.Conventions 公开),特别是 FindFullDocumentKeyFromNonStringIdentifier 委托,具有以下签名:

From the IAsyncDocumentSession interface, you can use the Conventions (exposed by Advanced.DocumentStore.Conventions), specifically the FindFullDocumentKeyFromNonStringIdentifier delegate, which has the following signature:

string FindFullDocumentKeyFromNonStringIdentifier(
    object id, Type type, bool allowNull);

这里是参数的作用:

  • id - 这是用作文档标识符的对象.在上面的示例中,它将是 DocumentKey 实例.由于这是作为 object(而不是 ValueType),此处将接受引用类型.
  • type - Type 实例,表示id 所属项目的类型.当调用 LoadAsync 时,这是 typeof(T).
  • allowNull - 在 ITypeConverter.ConvertFrom 的实现中作为 allowNull 参数传递,添加到 IdentityProviders 通过 Conventions 公开.
  • id - This is the object that is being used as the identifier for the document. In the above example, it would be the DocumentKey instance. Since this is typed as an object (and not a ValueType), a reference type will be accepted here.
  • type - The Type instance that represents the type of the item that the id belongs to. When calling LoadAsync<T>, this is typeof(T).
  • allowNull - This is passed as the allowNull parameter in the implementation of ITypeConverter.ConvertFrom that is added to the IdentityProviders exposed through Conventions.

这都可以包含在 IAsyncDocumentSession 上的扩展方法中(如果需要,也可以针对 IDocumentSession 进行修改),该方法是强类型的,如下所示:

This can all be wrapped up in an extension method on IAsyncDocumentSession (or modified for IDocumentSession if you want) that is strongly typed, like so:

static Task<T> LoadAsync<T, TId>(this IAsyncDocumentSession session, TId id)
{
    // Validate parameters.
    if (session == null) throw new ArgumentNullException("session");
    // Check if the id is null.
    if ((object) id == null) throw new ArgumentNullException("id");

    // Get the string id.
    string stringId = session.Advanced.DocumentStore.Conventions.
        FindFullDocumentKeyFromNonStringIdentifier(id, typeof(T), true);

    // Load using the string id.
    return session.LoadAsync<T>(stringId);
}

请注意,if ((object) id == null) 比较会对性能产生影响这种情况.

Note that the if ((object) id == null) comparison can have a performance impact in this scenario.

这篇关于如何在 RavenDB 中使用引用类型作为文档中的键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆