Session: What is a Session and How Does it Work
-
The Session, which is obtained from the Document Store, is a Unit of Work that represents
a single business transaction on a particular database. -
Basic document CRUD actions and document Queries are available through the
Session
.
More advanced options are available usingAdvanced
Session operations. -
The Session Tracks all Changes made to all entities that it has either loaded, stored, or queried on,
and persists to the server only what is needed whenSaveChanges()
is called. -
The number of server requests allowed per session is configurable (default is 30).
See: Change Maximum Number of Requests per Session -
In this page:
Unit of Work Pattern
Tracking Changes
- Using the Session, perform needed operations on your documents.
e.g. store a new document, modify an existing document, query your database, etc.
Any such operation 'loads' the documents to the Session for tracking. - The Session tracks all changes made to all entities that it has either loaded or stored.
You don't need to manually track the changes to these entities and decide what needs to be saved and what doesn't.
The Session will do it for you. - All these tracked changes are combined & persisted to the database only when calling
SaveChanges()
. - Entity tracking can be disabled if needed. See:
Batching
- Remote calls to a server over the network are among the most expensive operations an application makes.
The session optimizes this by batching all write operations it has tracked into the singleSaveChanges()
call. - The
SaveChanges()
call checks the Session state for all changes made to the tracked entities.
These changes are sent to the server as a single remote call that will complete transactionally.
In other words, either all changes are saved as a Single Atomic Transaction or none of them are.
OnceSaveChanges()
returns, it is guaranteed that the changes are persisted to the database. - The
SaveChanges()
is the only time when a RavenDB client sends updates to the server,
so you will experience a reduced number of network calls.
Store New Document Example
- The Client API, and the Session in particular, is designed to be as straightforward as possible.
Open the session, do some operations, and apply the changes to the RavenDB server. - The example below shows how to store a new document in the database using the Session.
// Obtain a Session from your Document Store.
using (IDocumentSession session = store.OpenSession())
{
// Create a new entity
Company entity = new Company { Name = "Company" };
// Mark the entity for storage in the Session.
session.Store(entity);
// Any changes made to the entity will now be tracked by the Session.
// However, the changes are persisted to the server only when 'SaveChanges()' is called.
session.SaveChanges();
// At this point the entity is persisted to the database as a new document.
// Since no database was specified when opening the Session, the Default Database is used.
}
Load & Edit Document Example
- The example below loads & edits an existing document and then saves the changes.
// Open a session.
using (IDocumentSession session = store.OpenSession())
{
// Load an existing document to the Session using its Id.
Company entity = session.Load<Company>(companyId);
// Edit the entity. The Session will track this change.
entity.Name = "Another Company";
session.SaveChanges();
// At this point, the change made is persisted in the database.
}
Identity Map Pattern
-
The session implements the Identity Map Pattern.
-
The first document
Load()
call goes to the server and fetches the document from the database.
The document is then saved as an entity in the Session's identity map. -
All subsequent
Load()
calls to the same document will simply retrieve the entity from the Session -
no additional calls to the server are made.
//When a document is loaded for a second time, it is retrieved from the identity map.
Assert.Same(session.Load<Company>(companyId), session.Load<Company>(companyId));
//This command will not throw an exception.
- Note: To override this and update an entity with the latest changes from the server see: Refresh an Entity
Reducing Server Calls (Best Practices) For:
The Select N+1 Problem
- The Select N+1 problem is common
with all ORMs and ORM-like APIs.
It results in an excessive number of remote calls to the server, which makes a query very expensive. - Make use of RavenDB's
include()
method to include related documents and avoid this issue.
See: Document Relationships
Large query results
- When query results are large and you don't want the overhead of keeping all results in memory, you can
Stream the Query Results.
A single server call is executed and the client can handle the results one by one. - Note: Paging also avoids getting all query results in one time, but multiple server calls are
generated - one per page retrieved.
Retrieving results on demand (Lazy)
- Query calls to the server can be delayed and executed on-demand as needed using
Lazily()
- See Perform Queries Lazily