2012-12-22 2 views
2

J'ai une classe que je veux utiliser une clé de document RavenDB:Comment utiliser un type de référence comme une clé dans un document RavenDB

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

J'ai aussi mis à exécution les ITypeConverter (pas .NET one, l'interface spécifique à RavenDB) pour convertir le type de référence en une chaîne (car dans la base de données, the keys are all really just strings).

Enfin, j'ai ajouté la mise en œuvre de ITypeConverter à la mise en œuvre IDocumentStore par la List<ITypeConverter> exposée à travers la propriété Conventions.IdentityProviders.

Cependant, la signature sur les LoadAsync<T> surcharges sur la mise en œuvre IAsyncDocumentSession ressembler à ceci (enlevé les signatures qui prennent plusieurs ids par souci de concision Aussi, le même que Load sur l'interface IDocumentSession.):

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

I ne veut vraiment pas utiliser les types de valeurs pour mes clés pour les raisons suivantes:

  • J'ai une abstraction qui n'a pas de contrainte sur le type de la clé. Créer des structures séparées pour refléter cela juste pour avoir des types de valeur sont très inconvénient.
  • Je n'ai pas un contrôle complet sur le type en étant limité à un type de valeur. Le type de valeur a un constructeur par défaut qui par défaut les valeurs d'une manière que je ne veux pas avoir à traiter partout ailleurs dans mon code.

Comment utiliser un type de référence comme clé de document dans RavenDB?

Répondre

2

Parce que tous les identifiants de documents sont stockés finalement stockés sous forme de chaînes dans RavenDB, la clé utilise la surcharge qui prend une chaîne:

LoadAsync<T>(string id); 

Depuis l'interface IAsyncDocumentSession, vous pouvez utiliser la Conventions (exposée par Advanced.DocumentStore.Conventions) , en particulier le délégué FindFullDocumentKeyFromNonStringIdentifier, qui a la signature suivante:

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

Voici ce que les paramètres font:

  • id - C'est l'objet qui est utilisé comme identifiant pour le document. Dans l'exemple ci-dessus, ce serait l'instance DocumentKey. Puisque ceci est tapé comme object (et non un ValueType), un type de référence sera accepté ici. L'instance Type qui représente le type de l'élément auquel appartient le id. Lorsque vous appelez le LoadAsync<T>, il s'agit du typeof(T).
  • - Ceci est passé comme le paramètre allowNull dans l'implémentation de ITypeConverter.ConvertFrom qui est ajouté au IdentityProviders exposé par Conventions.

Tout cela peut être enveloppé dans une méthode d'extension sur IAsyncDocumentSession (ou modifiés pour IDocumentSession si vous voulez) qui est fortement typé, comme ceci:

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); 
} 

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

Questions connexes