Telerik OpenAccess Classic

Telerik OpenAccess ORM Send comments on this topic.
Reference Types
Programmer's Guide > OpenAccess ORM Classic (Old API) > Programming With OpenAccess > The .NET Data Model > Reference Types

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.

Reference types are all types other than value types. Variables of reference types store a reference to the memory address of the value. Variables that are reference types can refer to the same object, therefore, an operation on one variable can affect the same object referred to by another variable.

User-defined persistent reference types

Instances of user-defined persistent reference types are the entities, which can be stored standalone in a database.

These classes can have fields of the following types:

 

Built-in value types (refer to the built-in value types section for more information)

 

Built-in "primitive" reference types (refer to the Built-in "primitive" reference types section for more information)

 

Enumerations

 

Nullable value types (only applicable with .NET 2.0, refer to the nullable value types section for more information)

 

Built-in collection types (refer to the .NET Framework Array and Collections Reference Types section for more information)

 

User-defined persistent value types (refer to the user-defined value types section for more information)

 

References to user-defined persistent reference types

The access level, i.e. private, protected, public or internal does not matter. Class fields (i.e. static in C# or Shared in VB.NET) and fields marked with the [TransientAttribute] are not persisted and therefore they can have any field type.

Inheritance is supported, the PersistentAttribute is not inherited, i.e. if a base class is persistent and its derived class also needs to be persistent, then both have to be marked as persistent.

In an OpenAccess ORM database, each object of a user-defined, persistence capable .NET Framework reference type is uniquely identifiable and can be individually retrieved from the database. By default, OpenAccess ORM also maintains an extent for the type (Extents are essentially collections of all the objects of a class type).

If such an object has fields that reference other persistent user-defined referenced types, these objects are separate entities and not necessarily loaded or deleted along with the referring object. However, due to the principle of "Persistence by Reachability" it is ensured, that all referenced objects are stored if the referring object is stored in the database.

Built-in "primitive" reference types

System.String

From the .NET framework point of view System.String is a (immutable) reference type. However OpenAccess ORM treats this type exactly like the supported built-in value types (Refer to the built-in value types section for more information).

OpenAccess.Blob

The OpenAccess.Blob type is predefined by OpenAccess ORM to deal with binary large objects. It can be used to store anything, which requires large storage capacity (such as image data).

This type is treated as a persistent primitive data type, which means that variables of this type cannot be stored individually in an OpenAccess ORM database, and they can only be used as fields in user-defined persistence capable classes.

System.Object

Any instance of a persistent user-defined reference type can be assigned. Refer to Mapping for detailed information.

The .NET Framework Array and Collections Reference Types

OpenAccess ORM supports the following .NET Framework interfaces and classes:

From System.Collections (.NET 1.1 and greater):

  • ArrayList
  • Queue
  • Stack
  • HashTable
  • SortedList

 

From System.Collections.Generic (.NET 2.0 and greater):

  • ICollection<T>
  • IList<T>
  • IDictionary<T>

 

From System.Collections.ObjectModel (.NET 3.0 and greater):

  • ObservableCollection<T>

 

Classes that derive from System.Array can be used as well.  Currently there are some limitations regarding this support by Telerik OpenAccess ORM: only one-dimensional persistent arrays are supported at the moment. It is not possible to have persistent arrays of arrays.

Any of these interfaces and classes can be used as data members in user-defined .NET Framework classes. They can only be used as data members in user-defined persistence capable classes.

When collection types define a certain order of their elements (i.e., ArrayList), OpenAccess ORM preserves this order.

OpenAccess ORM needs a strong typing of these collections. In case of, array fields this is implied by the field type. However, in case of, collection or dictionary fields this information must be provided by the user as described in the next section

Collection Item Types

In OpenAccess ORM, the default element type for arrays and collections is System.Object. In this case, all collection elements have to be instances of persistent reference types or persistent interfaces. To store .NET Framework value types in a collection, you must specify the element type in the OpenAccess ORM metadata description.

All elements of an array or a collection must be of the same type. Different .NET Framework built-in value types or .NET Framework user-defined value types cannot be mixed in an array or a collection. Similarly, instances of .NET Framework value types cannot be mixed with instances of .NET Framework reference types.

The element type of a collection field can be specified using the ItemType attribute on the respective member:

Copy Code
[OpenAccess.Persistent]
public class ICollectionType
{
  . . .
  [OpenAccess.ItemType(typeof(int))]
  private ICollection values;
  . . .
}

For classes implementing ICollection, the ItemType attribute takes one parameter. An exception to this is, classes that implement IDictionary, which requires two parameters. Refer to The ItemType Attribute for more information about the ItemType attribute.

The following ItemType attribute parameters are supported:

 

persistence capable user-defined .NET Framework reference types

 

persistence capable user-defined .NET Framework interfaces

 

persistence capable user-defined .NET Framework value types

 

Supported .NET Framework built-in value types (refer to the built-in value types section for more information)

 

System.String

Currently, in OpenAccess ORM, an [ItemType]of System.Object or of a persistence capable user-defined interface is not supported. The following example is an illustration:
Copy Code
[OpenAccess.Persistent]
interface MyInterface
{
  . . .
}

[OpenAccess.Persistent]
class MyClass
{
  System.Object field1; // OK
  MyInterface   field2; // OK

  [OpenAccess.ItemType( typeof( System.Object))]
  ArrayList     field3; // NOT OK!

  [OpenAccess.ItemType( typeof( MyInterface))]
  ArrayList     field4; // NOT OK!
}

Support for item types of System.Object and persistent interfaces is planned for a future release.

When an object with an array or collection data member is made persistent, the objects of user-defined .NET Framework reference types that the collection holds will also be made persistent as a result of the "persistence-by-reachability" principle. They become independent objects with their own object identity, and their membership in the array or collection is stored as a reference. This means that these objects are reachable like any other "normal" objects, an extent is maintained for their class, and so on. In addition, these objects will not necessarily be automatically retrieved from the database when the array or collection is retrieved, but rather only when they are explicitly requested or if a fetch group is set to fetch them along with their owner (Refer to FetchGroups for more information about fetch groups).

Retrieving Collections

When an object containing a collection data member is retrieved from the database, the collection is automatically reconstructed as a whole, with its elements containing references to the collection objects. If the collection contains elements of persistent .NET Framework reference types, these elements will not be automatically read from the database. Instead, a hollow object will be created for each of these objects and their data will be retrieved from the database at the time when the object is visited for the first time.

When iterating a collection of this type, one database call will be performed for every visited object.

One exception to this rule is that, while using persistence capable classes as elements within collections that do not allow duplicates, and therefore, have to be overwritten. For e.g. calling the Object.Equals() and Object.GetHashCode() methods within HashTable. In this case, while adding new elements to the collection, all existing collection elements are retrieved at once so that they can be compared. This is done when the collection is accessed for the first time; i.e., when a method is called.

The application cannot assume that it knows the actual class of instances assigned to classes implementing System.Collections or System.Array fields, although it is guaranteed that the actual class assignment is compatible with the type. OpenAccess ORM replaces the field values of System.Collections and System.Array types with instances of subclasses of the respective type. This is necessary to automatically track changes made to the collection or array. The same applies to the actual class of instances assigned to a field of a supported interface type. If, for example, your class has a field of type IList and you assign an object of an user-defined implementation of IList to this field, it is guaranteed that the field will be filled with an IList instance while reading it from the database; however, it could be an arbitrary class implementing the IList interface.

Implementing Your Own Collection Class

Collections are rarely, if ever, referenced by multiple objects. In all but exceptional cases, a collection object is the sole "property" of a single referencing object. Therefore in OpenAccess ORM, a collection is always owned directly by its parent object, i.e., the collection has no identity of its own.

If the collection should have its own identity you can achieve that by writing your own collection class. This can be a simple wrapper class for one of the standard collections as shown below:

Copy Code
[OpenAccess.Persistent]

class MyList : IList {

  private ArrayList myList = ArrayList();
  // you must implement all IList methods: Add, Clear, Contains, etc.
  // e.g., Add() . . .

  public int Add(Object value)
  {
    return myList.Add(value);
  }
  // ...
}

When you retrieve the parent object, only a hollow object for the collection is created. This saves the time required for reconstruction of the collection and the creation of the collection element objects. This can be effective when the parent object contains other data besides the collection that might be needed more often then the collection itself. On the other hand, this approach means that the collection object will appear in the database as an independent object with its own object ID and will be accessible from anywhere, not only through its parent object.

ObservableCollection

OpenAccess ORM supports Observable collections, which are new to the .NET 3.0 framework. ObservableCollection represents a dynamic data collection that provides notifications when items get added, removed, or when the whole list is refreshed. Refer to the Microsoft documentation for detailed information about ObservableCollection.

In order to use ObservableCollection you need to have .NET 3.0 installed, and then it can be used like IList<T>.