Lazy Operations
Some of the operations in RavenDB can be evaluated lazily (performed only when needed).
This section will describe each of the available lazy operations:
* Querying
* Loading
* Faceted searching
* Suggesting
Querying
To perform query below
IEnumerable<User> users = session
.Query<User>()
.Where(x => x.Name == "john");
as a lazy operation we have introduced Lazily()
extension method that will mark any type of queries as a lazy operation, so to perform above query as such an operation just mark it with this extension method like in example below.
Lazy<IEnumerable<User>> lazyUsers = session
.Query<User>()
.Where(x => x.Name == "John")
.Lazily();
To evaluate our lazyUsers
just access Value
property.
IEnumerable<User> users = lazyUsers.Value;
An action that will be executed when value gets evaluated can be passed to Lazily
. It is very handy in scenarios when you want to perform additional actions when value gets evaluated or when you want to execute all pending lazy operations at once.
IEnumerable<User> users = null;
IEnumerable<City> cities = null;
session
.Query<User>()
.Where(x => x.Name == "John")
.Lazily(x => users = x);
session
.Query<City>()
.Where(x => x.Name == "New York")
.Lazily(x => cities = x);
session.Advanced.Eagerly.ExecuteAllPendingLazyOperations();
Lazily
is a part of LinqExtensions
available in Raven.Client
namespace, so
using Raven.Client;
is mandatory.
Lazy Lucene queries are also possible.
Lazy<IEnumerable<User>> users = session.Advanced
.LuceneQuery<User>()
.WhereEquals("Name", "John")
.Lazily();
Loading
Loading lazily is done in a bit different manner, it can be achieved by using one of the methods available in session.Advanced.Lazily
property, so to perform below query
User user = session.Load<User>("users/1");
as a lazy operation just use one of the methods from session.Advanced.Lazily
like in example below
Lazy<User> lazyUser = session.Advanced.Lazily.Load<User>("users/1");
Value can be evaluated in same way as when Querying and Action that will be performed when value gets evaluated can also be passed.
User user = lazyUser.Value;
User user = null;
session.Advanced.Lazily.Load<User>("users/1", x => user = x);
session.Advanced.Eagerly.ExecuteAllPendingLazyOperations();
Other available lazy loading methods are:
1. LoadStartingWith where you can load all users with given key prefix.
var users = session.Advanced.Lazily.LoadStartingWith<User>("users/1");
2. Includes where additional documents will be loaded by given path.
If we consider having User
and City
classes as defined below
private class User
{
public string Id { get; set; }
public string Name { get; set; }
public string CityId { get; set; }
}
private class City
{
public string Id { get; set; }
public string Name { get; set; }
}
and store one User
and City
using (var session = store.OpenSession())
{
var user = new User
{
Id = "users/1",
Name = "John",
CityId = "cities/1"
};
var city = new City
{
Id = "cities/1",
Name = "New York"
};
session.Store(user);
session.SaveChanges();
}
then we will be able to perform code such as
var lazyUser = session.Advanced.Lazily
.Include("CityId")
.Load<User>("users/1");
var user = lazyUser.Value;
var isCityLoaded = session.Advanced.IsLoaded("cities/1"); // will be true
Faceted search
To take advantage of lazy Faceted search use ToFacetsLazy()
extension method from LinqExtensions
found in Raven.Client
namespace.
To change Faceted search from last step described here to lazy operation just substitute ToFacets
with ToFacetsLazy
.
Lazy<FacetResults> lazyFacetResults = session
.Query<Camera>("CameraCost")
.Where(x => x.Cost >= 100 && x.Cost <= 300)
.ToFacetsLazy("facets/CameraFacets");
FacetResults facetResults = lazyFacetResults.Value;
Suggesting
Similar practice as in Faceted search has been used in lazy suggestions. The SuggestLazy()
extension method is available in LinqExtensions
and can be used as a substitution to Suggest()
to mark operation as a lazy one.
Lazy<SuggestionQueryResult> lazySuggestionResult = session
.Query<User>()
.Where(x => x.Name == "John")
.SuggestLazy();
SuggestionQueryResult suggestionResult = lazySuggestionResult.Value;