-
Notifications
You must be signed in to change notification settings - Fork 10
Primary Key Handlers
Primary Key Handlers are used to map the Id column to/from the database.
A key handler has the following responsibilities:
- Identity which CLR type it is designed to handle
- provide the SqlMetaData required to build TableValueParameters
- work with a KeyAllocator to get the next key for a given table (used during Inserts)
- convert Id values to their CLR primitive value (used during Inserts and Deletes)
This last point is to cover cases where the models are not using raw primitive types as their Id property. For example, they may be wrapping a primitive in a custom type for type safety, so CustomerId can't be confused with OrderId even though they both represent a string or an int.
Below is an example of how you might implement a custom Primary Key Handler for a customer table, if the document had an Id property of type CustomerId.
public class CustomerId
{
public int Value { get;set; }
}
public class CustomerPrimaryKeyHandler : IPrimaryKeyHandler
{
public Type Type => typeof(CustomerId);
public SqlMetaData GetSqlMetaData(string name)
{
return new SqlMetaData(name, SqlDbType.Int);
}
[return: NotNullIfNotNull("id")]
public virtual object? ConvertToPrimitiveValue(object? id)
{
return (CustomerId)id.Value;
}
public object GetNextKey(IKeyAllocator keyAllocator, string tableName)
{
return new CustomerId { Value = keyAllocator.NextId(tableName) };
}
}The key concepts here are that:
- the
GetNextKeyshould always return a value that is the actual CLR type of the document's Id property - Nevermore will source a value from either the
Idproperty orGetNextKey, depending on which operation it is performing, and will use theConvertToPrimitiveValueto convert back to the primitive value required by aSqlCommandParameter.
There are two options available for configuring primary key handlers. One is to register them for a specific table, in its DocumentMap.
Id().KeyHandler(new CustomerPrimaryKeyHandler());The second is to register it globally in the store's configuration.
store.Configuration.PrimaryKeyHandlers.Register(new CustomerPrimaryKeyHandler());It will than apply automatically to any DocumentMap that has a document type with an Id of that type.
ℹ️ Tip:
There are 4 built in primary key handlers. One each for
string,int,long, andGuid. You can override any of the default implementations by implementing your ownIPrimaryKeyHandlerof any of these types and registering it. PerDocumentMapor globally through the store's configuration can both be used to do the override.
Overview
Getting started
Extensibility
Misc