The bundle works both on the server (using a PutTrigger and a DeleteTrigger) and on the client (using the
DocumentStoreListener and providing extension methods on
When a document is stored in a database, it generates "dummy" documents with following key format: "UniqueConstraints/" + entityName + "/" + propertyName + "/" + propertyValue. This way you don't need indexes (which would have to be not stale to check for uniqueness).
The listener works by using reflection when the document is stored in the database and generating metadata regarding its unique constraints. The reflection result is cached in the
ConcurrentDictionary to help with performance.
The put trigger acts whenever it finds a document being inserted with metadata constraints. It checks for existing documents in the constraints. If any existing document is found, it returns a VetoResult.Deny, informing the conflicting fields. This has to be checked on the client-side, using a try block for the OperationVetoedException.
If a document is being updated, the trigger updates the generated constraint document.
The delete trigger acts whenever it finds a document being deleted with constraints metadata . It deletes the referenced constraint documents.