Session: Loading Entities
There are various methods with many overloads that allow a user to download documents from a database and convert them to entities. This article will cover the following methods:
Load
The most basic way to load a single entity is to use one of the Load
methods.
T Load<T>(string id);
T Load<T>(ValueType id);
TResult Load<TResult>(
string id,
string transformer,
Action<ILoadConfiguration> configure);
TResult Load<TResult>(
string id,
Type transformerType,
Action<ILoadConfiguration> configure = null);
TResult Load<TTransformer, TResult>(
string id,
Action<ILoadConfiguration> configure = null)
where TTransformer : AbstractTransformerCreationTask, new();
Parameters | ||
---|---|---|
id | string or ValueType | Identifier of a document that will be loaded. |
transformer or transformerType | string or Type | Name or type of a transformer to use on a loaded document. |
configure | Action |
Additional configuration that should be used during an operation e.g. transformer parameters can be added. |
Return Value | |
---|---|
TResult | Instance of TResult or null if a document with a given ID does not exist. |
Example I
Employee employee = session.Load<Employee>("employees/1");
Example II
// loading 'employees/1'
// and transforming result using 'Employees_NoLastName' transformer
// which returns 'LastName' as 'null'
Employee employee = session.Load<Employees_NoLastName, Employee>("employees/1");
Non String Identifiers
The above examples show how to load a document by its string key.
What if a type of your entity's identifier is not a string? You need to use an overload of the Load
method that takes a parameter which type is ValueType
.
Example III
If you have an entity where an identifier is an integer number:
public class EntityWithIntegerId
{
c int Id { get; set; }
/*
...
*/
}
You can load it by specifying an integer value as the identifier:
EntityWithIntegerId entity = session.Load<EntityWithIntegerId>(1);
Converting to String Identifier
Even if the identifier is a string, you can use the Load<T>(ValueType)
overload. The client is aware of the ID generation conventions (collectionName/number),
so you could load the entity with the key employees/1
by using the code:
Employee employee = session.Load<Employee>(1);
Load with Includes
When there is a 'relationship' between documents, those documents can be loaded into a single request call using the Include + Load
methods.
ILoaderWithInclude<object> Include(string path);
ILoaderWithInclude<T> Include<T>(Expression<Func<T, object>> path);
ILoaderWithInclude<T> Include<T, TInclude>(Expression<Func<T, object>> path);
Parameters | ||
---|---|---|
path | string or Expression | Path in documents in which the server should look for a 'referenced' documents. |
Return Value | |
---|---|
ILoaderWithInclude | The Include method by itself does not materialize any requests, but returns loader containing methods such as Load . |
Example I
// loading 'products/1'
// including document found in 'Supplier' property
Product product = session
.Include<Product>(x => x.Supplier)
.Load<Product>("products/1");
Supplier supplier = session.Load<Supplier>(product.Supplier); // this will not make server call
Example II
// loading 'products/1'
// including document found in 'Supplier' property
Product product = session
.Include("Supplier")
.Load<Product>("products/1");
Supplier supplier = session.Load<Supplier>(product.Supplier); // this will not make server call
Example III
// loading 'products/1'
// including document found in 'Supplier' property
// transforming loaded product according to Products_Transformer
Product product = session
.Include<Product>(x => x.Supplier)
.Load<Products_Transformer, Product>("products/1");
Supplier supplier = session.Load<Supplier>(product.Supplier); // this will not make server call
Load - multiple entities
To load multiple entities at once use one of the following Load
overloads.
TResult[] Load<TResult>(IEnumerable<string> ids);
TResult[] Load<TResult>(IEnumerable<ValueType> ids);
TResult[] Load<TResult>(params ValueType[] ids);
TResult[] Load<TResult>(
IEnumerable<string> ids,
string transformer,
Action<ILoadConfiguration> configure = null);
TResult[] Load<TResult>(
IEnumerable<string> ids,
Type transformerType,
Action<ILoadConfiguration> configure = null);
TResult[] Load<TTransformer, TResult>(
IEnumerable<string> ids,
Action<ILoadConfiguration> configure = null)
where TTransformer : AbstractTransformerCreationTask, new();
Parameters | ||
---|---|---|
ids | IEnumerable |
Enumerable or array of IDs that should be loaded. |
transformer or transformerType | string or Type | Name or type of a transformer to use on loaded documents. |
configure | Action |
Additional configuration that should be used during an operation e.g. transformer parameters can be added. |
Return Value | |
---|---|
TResult[] | Array of entities in the exact same order as given IDs. If document does not exist, value at the appropriate position in array will be null . |
Example I
Employee[] employees = session.Load<Employee>(new List<string> { "employees/1", "employees/2" });
Employee employee1 = employees[0];
Employee employee2 = employees[1];
Example II
// loading 'employees/1' and 'employees/2'
// and transforming results using 'Employees_NoLastName' transformer
// which returns 'LastName' as 'null'
Employee[] employees = session
.Load<Employees_NoLastName, Employee>(new List<string> { "employees/1", "employees/2" });
Employee employee1 = employees[0];
Employee employee2 = employees[1];
LoadStartingWith
To load multiple entities that contain a common prefix, use the LoadStartingWith
method from the Advanced
session operations.
TResult[] LoadStartingWith<TResult>(
string keyPrefix,
string matches = null,
int start = 0,
int pageSize = 25,
string exclude = null,
RavenPagingInformation pagingInformation = null,
string skipAfter = null);
TResult[] LoadStartingWith<TTransformer, TResult>(
string keyPrefix,
string matches = null,
int start = 0,
int pageSize = 25,
string exclude = null,
RavenPagingInformation pagingInformation = null,
Action<ILoadConfiguration> configure = null,
string skipAfter = null);
Parameters | ||
---|---|---|
keyPrefix | string | the prefix for which documents should be returned |
matches | string | pipe ('|') separated values for which document keys (after 'keyPrefix') should be matched ('?' any single character, '*' any characters) |
start | int | the number of documents that should be skipped |
pageSize | int | the maximum number of documents that will be retrieved |
pagingInformation | RavenPagingInformation | used to perform rapid pagination on the server side |
exclude | string | pipe ('|') separated values for which document keys (after 'keyPrefix') should not be matched ('?' any single character, '*' any characters) |
configure | Action |
Additional configuration that should be used during an operation e.g. transformer parameters can be added. |
skipAfter | string | skip document fetching until given key is found and return documents after that key (default: null ) |
Return Value | |
---|---|
TResult[] | Array of entities matching given parameters. |
Example I
// return up to 128 entities with Id that starts with 'employees'
Employee[] result = session
.Advanced
.LoadStartingWith<Employee>("employees", null, 0, 128);
Example II
// return up to 128 entities with Id that starts with 'employees/'
// and rest of the key begins with "1" or "2" e.g. employees/10, employees/25
Employee[] result = session
.Advanced
.LoadStartingWith<Employee>("employees/", "1*|2*", 0, 128);
Example III
// return up to 128 entities with Id that starts with 'employees/'
// and rest of the Id have length of 3, begins and ends with "1"
// and contains any character at 2nd position e.g. employees/101, employees/1B1
// and transform results using 'Employees_NoLastName' transformer
Employee[] result = session
.Advanced
.LoadStartingWith<Employees_NoLastName, Employee>("employees/", "1?1", 0, 128);
Stream
Entities can be streamed from the server using one of the following Stream
methods from the Advanced
session operations.
IEnumerator<StreamResult<T>> Stream<T>(
Etag fromEtag,
int start = 0,
int pageSize = int.MaxValue,
RavenPagingInformation pagingInformation = null,
string transformer = null,
Dictionary<string, RavenJToken> transformerParameters = null);
IEnumerator<StreamResult<T>> Stream<T>(
string startsWith,
string matches = null,
int start = 0,
int pageSize = int.MaxValue,
RavenPagingInformation pagingInformation = null,
string skipAfter = null,
string transformer = null,
Dictionary<string, RavenJToken> transformerParameters = null);
Parameters | ||
---|---|---|
fromEtag | Etag | ETag of a document from which stream should start (mutually exclusive with 'startsWith') |
startsWith | string | prefix for which documents should be streamed (mutually exclusive with 'fromEtag') |
matches | string | pipe ('|') separated values for which document keys (after 'keyPrefix') should be matched ('?' any single character, '*' any characters) |
start | int | number of documents that should be skipped |
pageSize | int | maximum number of documents that will be retrieved |
pagingInformation | RavenPagingInformation | used to perform rapid pagination on the server side |
skipAfter | string | skip document fetching until given key is found and return documents after that key (default: null ) |
transformer | String | name of transformer (default: null ) |
transformerParameters | Dictionary<string, RavenJToken> | parameters to pass to the transformer (default: null ) |
Return Value | |
---|---|
IEnumerator<StreamResult> | Enumerator with entities. |
Example I
IEnumerator<StreamResult<Employee>> enumerator = session.Advanced.Stream<Employee>("employees/");
while (enumerator.MoveNext())
{
StreamResult<Employee> employee = enumerator.Current;
}
Example 2
Using the following transformer:
public class SimpleTransformer : AbstractTransformerCreationTask
{
public class Result
{
public string Name { get; set; }
}
public override TransformerDefinition CreateTransformerDefinition(bool prettify = true)
{
return new TransformerDefinition
{
Name = "SimpleTransformer",
TransformResults = "from r in results select new { Name = Parameter(\"Name\") }"
};
}
}
StreamDocs using the SimpleTransformer defined above and one supplied parameter:
var transformer = new SimpleTransformer();
transformer.Execute(store);
using (IEnumerator<StreamResult<SimpleTransformer.Result>> enumerator = session.Advanced.Stream<SimpleTransformer.Result>("people/", transformer: transformer.TransformerName, transformerParameters: new Dictionary<string, RavenJToken> { { "Name", "Bill" } }))
{
while (enumerator.MoveNext())
{
StreamResult<SimpleTransformer.Result> result = enumerator.Current;
string name = result.Document.Name;
Assert.Equal("Bill", name); // Should be true
}
}
Remarks
Information
Entities loaded using Stream
will be transient (not attached to session).
Caution
fromEtag does not do any filtrations on the server-side based on the specified in streaming function return type (e.g. Employee
). It will return all documents from given Etag even if their Raven-Clr-Type
does not match the return type, which may cause potential casting errors. Set return type to object
, dynamic
or RavenJObject
to address a situation where documents with different types might be returned.
IsLoaded
To check if entity is attached to session, e.g. it has been loaded previously, use the IsLoaded
method from Advanced
session operations.
bool IsLoaded(string id);
Parameters | ||
---|---|---|
id | string | Entity Id for which the check should be performed. |
Return Value | |
---|---|
bool | Indicates if an entity with a given ID is loaded. |
Example
bool isLoaded = session.Advanced.IsLoaded("employees/1"); // false
Employee employee = session.Load<Employee>("employees/1");
isLoaded = session.Advanced.IsLoaded("employees/1"); // true