Telerik OpenAccess Classic

Telerik OpenAccess ORM Send comments on this topic.
The Persistent Attribute
Programmer's Guide > OpenAccess ORM Classic (Old API) > Programming With OpenAccess > The Persistent Attribute

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.

The [OpenAccess.Persistent] attribute is used to declare a class, interface, or structure as persistence capable. This attribute must be specified for each type for which instances should be made persistent. A persistent interface is used to get an Extent of all classes that implement the interface. For each type, only one [Persistent] attribute can be specified.

During enhancement and registration the OpenAccess ORM enhancer uses this attribute to determine which classes should be made persistence capable and which classes have to be registered in the database schema. The OpenAccess ORM runtime system also makes use of this attribute to get information about persistent classes.

The [Persistent] attribute is implemented by the class OpenAccess.PersistentAttribute.

Properties

The [Persistent] attribute has a number of modifiable properties to define the characteristics of a persistent type.

Alias
 

The Alias property specifies an alternative name, an alias, for the name of a persistent type. By default, the short name of the type without its namespace is used.

Alias names are convenient for specifying classes in OQL queries. An alias can be specified as follows:

Copy Code
[Persistent(Alias="Addr")]
public class Address
{
  // . . .
}

In the example given above the [Persistent] attribute, along with an Alias "Addr", is applied to the Address class.

Specifying Alias names is useful in the following scenarios: -

 

Two classes with the same name in two different namespaces.

For e.g. If we have an Employee class in two different namespaces, the only way to specify the right type in a query is by using the Alias property:

Copy Code
namespace ProjectA
  [Persistent(Alias="ProjectAEmployee")]
  public class Employee
  {
  // . . .
  }

Copy Code
namespace ProjectB
  [Persistent(Alias="ProjectBEmployee")]
  public class Employee
  {
  // . . .
  }

Now, if you want to query the Employee class in the Project A namespace, you should write the query as:

Copy Code
SELECT * FROM ProjectAEmployeeExtent

The above statement will query the Employee class and will return all the Employee objects in the Project A namespace.

Similarly, if you want to query the Employee class in the Project B namespace, you should write the query as:

Copy Code
SELECT * FROM ProjectBEmployeeExtent

The above statement will query the Employee class and will return all the Employee objects in the Project B namespace.

Therefore, using the Alias property helps you to specify the right type in a query.

 

An alias is also useful when you want to rename your classes without having to change the queries.

For e.g., If we want to rename the Address class (which has been specified an alias "Addr" above) to EmployeeAddress, we can do so without having to change the query, i.e., the queries can yet be written as:

Copy Code
SELECT * FROM %AliasName%Extent

In our example the %AliasName% will be replaced by Addr:

Copy Code
SELECT * FROM AddrExtent

The alias can also be applied later, that means in our Address renaming scenario you can change the Address class name to EmployeeAddress and apply the alias "Address" to the class:

Copy Code
public class Address
{
  // . . .
}

->

[Persistent(Alias="Address")]
public class EmployeeAddress
{
  // . . .
}


In this case too the queries will remain the same as before, since the earlier class name and the alias name are the same, i.e., Address.

Once the alias name is specified the user needs to use the alias name in a query, even when there is just one class.

For e.g., if we have specified the following:

Copy Code
[Persistent(Alias="Emp")]
public class Employee
 {
  // . . .
 }

We need use the alias name Emp in any query on the above Employee class. If we specify the class name (Employee) in a query (for e.g., SELECT * FROM EmployeeExtent) we will get an exception like: No class found for extent "EmployeeExtent".

Therefore, whenever we need to query the above Employee class we will have to specify the alias name in the query like:

Copy Code
SELECT * FROM EmpExtent
Identity
 

The Identity property determines whether the identity for objects is automatically provided by the runtime system (internal identity) or is provided by the values of certain fields of an object.

When Multiple Field identity is used within an inheritance hierarchy, all classes of that hierarchy must share the same identity type. Furthermore the fields to be used must be declared in the least-derived class of that hierarchy in case of flat and vertical mapping. In case of horizontal mapping, the identity information is specified at the next derived class (refer to Multiple Field Identity for more information).

IdentityField
 

The IdentityField property determines the field used for single field identity. When setting this property to the name of a field of the class marked with the [Persistent] attribute, the named field is treated as the holder of the primary key (refer to Single Field Identity for more information).

When Single Field identity is used within an inheritance hierarchy, all classes of that hierarchy must share the same identity type. Furthermore the fields to be used must be declared in the least-derived class of that hierarchy in case of flat and vertical mapping.

In case of horizontal mapping, the identity information is specified at the next derived class and if the IdentityField specified belongs to the base class, it has to be accessible from the derived classes. Therefore, declaring this field as "Protected" might be the best way, since if this field is declared as "Private" the enhanced code will not be able to access this field. The enhancer will check this and report an error.

VersionField
 

The VersionField determines the field used for optimistic concurrency control. Use the Forward Mapping Wizard to specify the VersionField mapping entry.

The VersionField information can be written to either the XML file (App.config) or to the source code. Use the Options Dialog to specify the location of the VersionField.

By default the VersionField is written to the source code.

The VersionField will be written to the location specified in the Options Dialog, only for new entries, i.e., only when you change something for the VersionField will the entry be made as per your setting.

The XML entry for the VersionField appears as:

Copy Code
<class name="Address">
     <extension key="db-optimistic-locking">
          <extension key="field-name" value="version" />
     </extension>
</class>

In case of source code, while setting this property to the name of a field of the class marked with the [Persistent] attribute, the named field is treated as the holder of the version information. [Persistent(VersionField="yy")] is used to declare that field "yy" should be used to perform concurrent change detection. For e.g.:

Copy Code
[OpenAccess.Persistent(VersionField="version")]
public class Address
{
  private short version;

  public short VERSION
  {
    get { return version; }
    set { version = value; }
  }
  // ...

When version field is set within an inheritance hierarchy, all classes of that hierarchy share the same version field setting. Furthermore the fields to be used must be declared in the least-derived class of that hierarchy in case of flat and vertical mapping.

In case of horizontal mapping, the version information is specified at the next derived class, and if the VersionField specified belongs to the base class, it has to be accessible from the derived classes. Therefore, declaring this field as "Protected" might be the best way, since if this field is declared as "Private" the enhanced code will not be able to access this field. The enhancer will check this and report an error.