-
Notifications
You must be signed in to change notification settings - Fork 12
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
GetNextKey
should always return a value that is the actual CLR type of the document's Id property - Nevermore will source a value from either the
Id
property orGetNextKey
, depending on which operation it is performing, and will use theConvertToPrimitiveValue
to 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 ownIPrimaryKeyHandler
of any of these types and registering it. PerDocumentMap
or globally through the store's configuration can both be used to do the override.
Overview
Getting started
Extensibility
Misc