Telerik OpenAccess Classic

Telerik OpenAccess ORM Send comments on this topic.
How to: Load Object Graphs (Fetch Plans)
Programmer's Guide > OpenAccess ORM Classic (Old API) > OpenAccess Tasks > Working with Objects > How to: Load Object Graphs (Fetch Plans)

Glossary Item Box

This documentation article is a legacy resource describing the functionality of the deprecated OpenAccess Classic only. The contemporary documentation of Telerik OpenAccess ORM is available here.

Fetch Plans are very powerful feature of Telerik OpenAccess ORM. When interacting with an object, fetch plans provide the possibility to fine-tune the fetching of the fields we are using from the database and not the whole object. This is resulting better performance and less load on the database server.

A Fetch Plan represents collection of strings. These strings are the names of the Fetch Groups which includes the fetched fields for each of the persistent classes. A field can be a part of a given fetch group when marked with the [FetchField] attribute with the name of the desired fetch group given as parameter.  There can be more than one FetchField attributes assigned to a field so it can be fetched in different groups depending on the project’s business logic.

C# Copy Code
[FetchField("myGroup")]
private Employee employee;  
VB .NET Copy Code
<FetchField("myGroup")> _
Private employee As Employee

There are different ways to define fetch groups and organize the fetch plan: defining attributes by hand, storing information in the App.config, etc. In this topic however the focus is on the easier and more intuitive visual support, provided by the OpenAccess wizards inside Visual Studio.

The OpenAccess Forward Mapping Wizard is used for defining fetch groups. Open the wizard and choose the class that you want to define a group for, and select the FetchGroup tab.

Defining fetch groups with the Forward Mapping wizard works for reverse mapped persistent models as well as for forward mapped.

In the following examples a reverse mapped model of the Northwind database is used.

 

In the FetchGroup tab of the wizard click on the Add/Remove button and specify a name for the new fetch group. Since a fetch group is defined for the chosen class, a column of check boxes is displayed next to the class fields. Only the fields that have this check will be fetched.

 

If a given field is a reference to another object the following fetch group feature can be used - definition of the next fetch group that is executed when accessing the reference field/property:

 

That means not all fields from the referenced object will be fetched but only those that are specified in the next fetch group.

In the shown example, there is a fetch group defined for the Order class called “theGroup". The OrderDetails reference field is among the selected for fetching and a Next Fetch Group also called “theGroup” is defined for it. This group is also defined for the OrderDetails class and the product field is selected. The same step is repeated for the Product class where only the product name and id are added for fetching. Defining the same group as next group for a reference field is allowed. Although different groups can be used as well.


To get advantage of the defined fetch groups they should be added to a fetch plan by calling the FetchPlan.Add() method from the object scope. All defined groups have to be added by this method except the case when groups are embedded in each other with the "Next fetch group" option. Then only the root fetch group could be added.

It is not a good practice to clear the current fetch plan before adding the new fetch groups. This is done by the scope.FetchPlan.Clear() method. The fetch plan by default contains only the "Default" fetch group. The "Default" fetch group tells the object scope to retrieve all the value fields of an object and only the ID’s of the reference ones.

In case you need to clear the current fetch plan by invoking the FetchPlan.Clear() method, the Default fetch group will be also removed. In this case you should explicitly set which fields from the reference object should be obtained from the new fetch group. Consider the Product and Category classes which are mapped to the corresponding Northwind table. A product object has reference to a category. If you want to execute the following statement:

C# Copy Code
scope.FetchPlan.Clear();
scope.FetchPlan.Add("ProductFetchGroup");
var result = scope.Extent<Product>();
foreach (Product product in result)
{
               
string categoryName = product.Category != null ? product.Category.CategoryName : string.Empty;
               Console.WriteLine(
"{0}\t{1}\t{2}", product.ProductID, categoryName, product.ProductName);
}

the ProductFetchGroup should include the Product.productId, Product.productName and Category.categoryName fields, otherwise additional calls to the database will be made.

Here is the complete sample code of adding fetch groups to a plan:

C# Copy Code
IObjectScope scope = ObjectScopeProvider1.GetNewObjectScope();
scope.FetchPlan.Add("theGroup");
var result = from o
in scope.Extent<Order>()
                select o;

foreach (Order o in result.ToList())
{
   
foreach (OrderDetail od in o.OrderDetails)
   {
      Console.WriteLine(od.Product.ProductName);
   }
}
VB .NET Copy Code
Dim scope As IObjectScope = ObjectScopeProvider1.GetNewObjectScope()
scope.FetchPlan.Add("theGroup")
Dim result = From o In scope.Extent(Of Order)() _
             Select o
For Each o As Order In result.ToList()
   For Each od As OrderDetail In o.OrderDetails
      Console.WriteLine(od.Product.ProductName)
   Next
Next

When access is required to only some of the properties of a persistent class that is few levels deeper in the object graph, using the appropriate fetch plan can be a considerable performance booster. In the described case only the order objects are extracted. The logic is that access is needed to all their details, the products of the details and only the names of those products. By "telling" the scope’s fetch plan to use the defined fetch group hierarchy all this is done and no additional calls to the database are made.