Как использовать ссылочный тип в качестве ключа в документе в 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) сравнение может оказать влияние на производительность в этом сценарии.

Другие вопросы по тегам