Global Identifier Generation Conventions
FindCollectionName and FindCollectionNameForDynamic
Documents that have the same @collection
metadata belong to the same collection on the server side. Collection names are also used to build document identifiers. There are two functions that the client uses to determine a collection name for a given type. The first one is used for standard objects with a well-defined type:
FindCollectionName = type => // function that provides the collection name based on the entity type
The second one is dedicated for dynamic objects:
FindCollectionNameForDynamic =
dynamicObject => // function to determine the collection name for the given dynamic object
What is a Dynamic Object?
The FindCollectionNameForDynamic
only works on objects that inherit from IDynamicMetaObjectProvider interface. In .NET there are two built-in types that implement that interface, the ExpandoObject and DynamicObject.
For example, if we want to determine a collection using a Collection
property from a dynamic object, we need to set FindCollectionNameForDynamic
as follows:
FindCollectionNameForDynamic = o => o.Collection
After that we can store our dynamic object as follows:
dynamic car = new ExpandoObject();
car.Name = "Ford";
car.Collection = "Cars";
session.Store(car);
dynamic animal = new ExpandoObject();
animal.Name = "Rhino";
animal.Collection = "Animals";
session.Store(animal);
TransformTypeCollectionNameToDocumentIdPrefix
Collection names determined by recently described convention functions aren't directly used as prefixes in document identifiers. There is a convention function called TransformTypeCollectionNameToDocumentIdPrefix
which takes the collection name and produces the prefix:
TransformTypeCollectionNameToDocumentIdPrefix =
collectionName => // transform the collection name to the prefix of a identifier, e.g. [prefix]/12
Its default behavior for a collection which contains one upper character is to simply convert it to lower case string. Users
would be transformed into users
. For collection names containing more upper characters, there will be no change. The collection name: LineItems
would output the following prefix: LineItems
.
FindClrTypeName and FindClrType
In the metadata of all documents stored in a database, you can find the following property which specifies the client-side type. For instance:
{
"Raven-Clr-Type": "Orders.Shipper, Northwind"
}
This property is used by RavenDB client to perform a conversion between a .NET object and a JSON document stored in a database. A function responsible for retrieving the CLR type of an entity is defined by FindClrTypeName
convention:
FindClrTypeName = type => // use reflection to determine the type;
To properly perform the revert conversion that is from a JSON result into a .NET object, we need to retrieve the CLR type from the Raven-Clr-Type
metadata:
FindClrType = (id, doc) =>
{
if (doc.TryGet(Constants.Documents.Metadata.Key, out BlittableJsonReaderObject metadata) &&
metadata.TryGet(Constants.Documents.Metadata.RavenClrType, out string clrType))
return clrType;
return null;
},
FindIdentityProperty
The client must know where in your entity an identifier is stored to be properly able to transform it into JSON document. It uses the FindIdentityProperty
convention for that. The default and very common convention is that a property named Id
is the identifier, so is the default one:
FindIdentityProperty = memberInfo => memberInfo.Name == "Id"
You can provide a customization based on the MemberInfo
parameter to indicate which property or field keeps the identifier. The client will iterate over all object properties and take the first one according to the defined predicate.
FindIdentityPropertyNameFromCollectionName
It can happen that sometimes the results returned by the server don't have identifiers defined (for example if you run a projection query). However, they have @collection
in metadata.
To perform the conversion into a .NET object, a function that finds the identity property name for a given entity name is applied:
FindIdentityPropertyNameFromCollectionName = collectionName => "Id"
IdentityPartsSeparator
According to the default, convention document identifiers have the following format: [collectionName]/[identityValue]-[nodeTag]
. The slash character (/
) separates the two parts of an identifier.
You can overwrite it by using IdentityPartsSeparator
convention. Its default definition is:
IdentityPartsSeparator = "/"