Session: How to Subscribe to Events
The concept of events provides users with a mechanism to perform custom actions in response to operations taken in a session.
The event is invoked when a particular action is executed on an entity or querying is performed.
Subscribing to an event
Subscribing an event can be done in the DocumentStore
object, which will be valid for all future sessions or subscribing in an already opened session with session.Advanced
which will overwrite the existing event for the current session.
OnBeforeStore
This event is invoked as a part of SaveChanges
but before it is actually sent to the server.
It takes the argument BeforeStoreEventArgs
that consists of the Session
entity's ID and the entity itself.
Example
Say we want to discontinue all of the products that are not in stock.
private void OnBeforeStoreEvent(object sender, BeforeStoreEventArgs args)
{
var product = args.Entity as Product;
if (product?.UnitsInStock == 0)
{
product.Discontinued = true;
}
}
After we subscribe to the event, every stored entity will invoke the method.
// Subscribe to the event
store.OnBeforeStore += OnBeforeStoreEvent;
// Open a session and store some entities
using (var session = store.OpenSession())
{
session.Store(new Product
{
Name = "RavenDB v3.5",
UnitsInStock = 0
});
session.Store(new Product
{
Name = "RavenDB v4.0",
UnitsInStock = 1000
});
session.SaveChanges(); // Here the method is invoked
}
OnBeforeDelete
This event is invoked as a part of SaveChanges
, but before it actually sends the deleted entities to the server.
It takes the argument BeforeDeleteEventArgs
, that consists of the Session
entity's ID and the entity itself.
Example
To prevent anyone from deleting entities we can create a method as follows:
private void OnBeforeDeleteEvent(object sender, BeforeDeleteEventArgs args)
{
throw new NotSupportedException();
}
and subscribe it to the session:
// Subscribe to the event
store.OnBeforeDelete += OnBeforeDeleteEvent;
// Open a session and delete entity
using (var session = store.OpenSession())
{
var product = session.Load<Product>("products/1-A");
session.Delete(product);
session.SaveChanges(); // NotSupportedException will be thrown here
}
OnAfterSaveChanges
This event is invoked after the SaveChanges
is returned. It takes the argument AfterSaveChangesEventArgs
that consists of the Session
entity's ID and the entity itself with the updated metadata from the server.
Example
If we want to log each entity that was saved, we can create a method as follows:
private void OnAfterSaveChangesEvent(object sender, AfterSaveChangesEventArgs args)
{
if (Log.IsInfoEnabled)
Log.Info($"Document '{args.DocumentId}' was saved.");
}
OnBeforeQuery
This event is invoked just before the query is sent to the server.
It takes the argument BeforeQueryEventArgs
, that consists of the Session
and the IDocumentQueryCustomization
.
Example I
If you want to disable caching of all query results, you can implement the method as follows:
private void OnBeforeQueryEvent(object sender, BeforeQueryEventArgs args)
{
args.QueryCustomization.NoCaching();
}
Example II
If you want each query to wait for non-stale results you can create an event as follows:
private void OnBeforeQueryEvent(object sender, BeforeQueryEventArgs args)
{
args.QueryCustomization.WaitForNonStaleResults(TimeSpan.FromSeconds(30));
}
OnBeforeConversionToDocument
This event is invoked before conversion of an entity to blittable JSON document. E.g. it's called when sending a document to a server.
It takes the argument BeforeConversionToDocumentEventArgs
, that consists of an entity, its ID and the session instance.
private void OnBeforeConversionToDocument(object sender, BeforeConversionToDocumentEventArgs args)
{
if (args.Entity is Item item)
item.Before = true;
}
OnAfterConversionToDocument
This event is invoked after conversion of an entity to blittable JSON document.
It takes the argument AfterConversionToDocumentEventArgs
, that consists of an entity, its ID, the session instance and converted JSON document.
private void OnAfterConversionToDocument(object sender, AfterConversionToDocumentEventArgs args)
{
if (args.Entity is Item item)
{
if (args.Document.Modifications == null)
args.Document.Modifications = new DynamicJsonValue();
args.Document.Modifications["After"] = true;
args.Document = args.Session.Context.ReadObject(args.Document, args.Id);
item.After = true;
}
}
OnBeforeConversionToEntity
This event is invoked before conversion of a JSON document to an entity. E.g. it's called when loading a document.
It takes the argument BeforeConversionToEntityEventArgs
, that consists of a JSON document, its ID and type, and the session instance.
private void OnBeforeConversionToEntity(object sender, BeforeConversionToEntityEventArgs args)
{
var document = args.Document;
if (document.Modifications == null)
document.Modifications = new DynamicJsonValue();
document.Modifications["Before"] = true;
args.Document = args.Session.Context.ReadObject(document, args.Id);
}
OnAfterConversionToEntity
This event is invoked after conversion of a JSON document to an entity.
private void OnAfterConversionToEntity(object sender, AfterConversionToEntityEventArgs args)
{
if (args.Entity is Item item)
item.After = true;
}
It takes the argument AfterConversionToEntityEventArgs
, that consists of a JSON document, its ID, the session instance and a converted entity.