2

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

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

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

最后,我通过通过属性公开的方式ITypeConverterIDocumentStore实现添加到实现中。List<ITypeConverter>Conventions.IdentityProviders

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

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

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

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

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

4

1 回答 1

2

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

LoadAsync<T>(string id);

IAsyncDocumentSession界面中,您可以使用Conventions(exposed by Advanced.DocumentStore.Conventions),特别是FindFullDocumentKeyFromNonStringIdentifier委托,它具有以下签名:

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

以下是参数的作用:

  • id- 这是用作文档标识符的对象。在上面的示例中,它将是DocumentKey实例。由于这是作为object(而不是 a ValueType)类型的,因此此处将接受引用类型。
  • type-Type表示id所属项目类型的实例。打电话LoadAsync<T>的时候是这样的typeof(T)
  • allowNull- 这是作为allowNull参数传递的,通过ITypeConverter.ConvertFrom添加到IdentityProviders暴露的实现中Conventions

这都可以包含在强类型的扩展方法中IAsyncDocumentSession(或IDocumentSession根据需要进行修改),如下所示:

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)在这种情况下,比较可能会对性能产生影响。

于 2012-12-22T17:41:20.777 回答