Как использовать ссылочный тип в качестве ключа в документе в RavenDB
У меня есть класс, который я хочу использовать для ключа документа в RavenDB:
public class DocumentKey
{
public string Namespace { get; set; }
public string Id { get; set; }
}
Я также реализовал ITypeConverter
(не.NET, а специфичный для RavenDB) интерфейс для преобразования из ссылочного типа в строку (потому что в базе данных все ключи на самом деле являются просто строками).
Наконец, я добавил реализацию ITypeConverter
к IDocumentStore
реализация через List<ITypeConverter>
подвергается через Conventions.IdentityProviders
имущество.
Тем не менее, подпись на LoadAsync<T>
перегрузки на IAsyncDocumentSession
реализация выглядит следующим образом (убраны подписи, которые для краткости принимают несколько идентификаторов). Load
на IDocumentSession
интерфейс):
LoadAsync<T>(string id);
LoadAsync<T>(ValueType id);
Я действительно не хочу использовать типы значений для моих ключей по следующим причинам:
- У меня есть абстракция, которая не имеет ограничений на тип ключа. Создание отдельных структур для отражения этого просто для того, чтобы иметь типы значений, очень неудобно.
- Я не имею полного контроля над типом, будучи ограниченным типом значения. Тип значения имеет конструктор по умолчанию, который устанавливает значения по умолчанию таким образом, что я не хочу иметь дело с другими частями моего кода.
Как я могу использовать ссылочный тип в качестве ключа документа в RavenDB?
1 ответ
Поскольку все идентификаторы документа в конечном итоге хранятся в виде строк в RavenDB, ключ использует перегрузку, которая принимает строку:
LoadAsync<T>(string id);
От IAsyncDocumentSession
интерфейс, вы можете использовать Conventions
(выставлено Advanced.DocumentStore.Conventions
), в частности, FindFullDocumentKeyFromNonStringIdentifier
делегат, имеющий следующую подпись:
string FindFullDocumentKeyFromNonStringIdentifier(
object id, Type type, bool allowNull);
Вот что делают параметры:
id
- Это объект, который используется в качестве идентификатора для документа. В приведенном выше примере это будетDocumentKey
пример. Так как это напечатано какobject
(а не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)
сравнение может оказать влияние на производительность в этом сценарии.