如何在RavenDB中将引用类型用作文档中的键

时间:2012-12-22 17:41:21

标签: ravendb composite-key

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

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

我还实现了ITypeConverter(不是.NET,特定于RavenDB)接口,从引用类型转换为字符串(因为在数据库中,the keys are all really just strings)。

最后,我通过ITypeConverter属性公开的IDocumentStoreList<ITypeConverter>实施添加了Conventions.IdentityProviders的实施。

但是,LoadAsync<T>实施的IAsyncDocumentSession重载上的签名如下所示(为了简洁起见,删除了带有多个ID的签名。此外,与Load上的IDocumentSession相同{1}}界面):

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

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

  • 我有一个抽象,它没有对密钥类型的约束。创建单独的结构来镜像它只是为了获得值类型非常不方便。
  • 通过限制为值类型,我无法完全控制类型。值类型有一个默认构造函数,它以我不想在代码中的其他地方处理的方式默认值。

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

1 个答案:

答案 0 :(得分:2)

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

LoadAsync<T>(string id);

IAsyncDocumentSession界面中,您可以使用Conventions(由Advanced.DocumentStore.Conventions公开),特别是FindFullDocumentKeyFromNonStringIdentifier委托,其中包含以下签名:

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

参数的作用如下:

  • id - 这是用作文档标识符的对象。在上面的示例中,它将是DocumentKey实例。由于此类型为object(而不是ValueType),因此此处将接受引用类型。
  • type - 表示id所属项目类型的Type实例。致电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); } )强类型,如下所示:

{{1}}

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