如何在 RavenDB 中使用引用类型作为文档中的键 [英] How to use a reference type as a key in a document in 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).
最后,我通过公开的
属性.List
将ITypeConverter
的实现添加到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 theDocumentKey
instance. Since this is typed as anobject
(and not aValueType
), a reference type will be accepted here.type
- TheType
instance that represents the type of the item that theid
belongs to. When callingLoadAsync<T>
, this istypeof(T)
.allowNull
- This is passed as theallowNull
parameter in the implementation ofITypeConverter.ConvertFrom
that is added to theIdentityProviders
exposed throughConventions
.
这都可以包含在 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屋!