Skip to main content
A newer version of this page is available. .

Basics of Creating Persistent Objects for Existing Data Tables

  • 6 minutes to read

To access an existing data table in a database and work with it using the functionality provided by eXpress Persistent Objects(XPO), you need to create a persistent object that describes this table. The persistent object should identify the target table’s name and required data fields. If you want to work with two or more tables linked by relationships, you need to create objects for each table, and then define relationships between objects using specific attributes.

It’s possible to automatically generate persistent classes for your existing databases. See Generating Persistent Objects for Existing Data Tables to learn more.

This topic provides basic information on how to create a persistent object for an existing data table manually. Creating relationships between objects is not described here. See the Object Relationships topic for more details on implementing relationships between tables/objects.

Basics of Creating Persistent Objects for Existing Data Tables

The easiest way to create a persistent object is to declare a class derived from the XPBaseObject class or one of its descendants (XPLiteObject, XPCustomObject or XPObject).

To work correctly with an existing data table using XPO, the table must contain a key field. If the table contains a key field, you can derive a persistent object from the XPBaseObject or XPLiteObject class.

The persistent class must declare public properties (persistent properties) that represent data fields in the target data table. It’s not necessary to declare persistent properties for all fields. You can only declare properties for required fields. The types of the properties must match the types of the data fields.

Typically, the name of the class should match the name of the target data table, and the names of created persistent properties should match the names of corresponding data fields. However, it’s possible to create the class and/or its persistent properties with different names, and then map them to corresponding data objects via the PersistentAttribute attribute.

If a key field’s values need to be obtained, declare a corresponding persistent property and mark it with the KeyAttribute attribute. You can omit declaring a key persistent property if it’s not required for your task.

By default, persistent objects are handled within the scope of the default session. If you want to work with a persistent object using a non-default session, you need to add a public constructor to the persistent class with a Session parameter. This constructor should call the base constructor, passing it the specified session (see examples below). For more information on sessions, see the Session section.

In specific instances you may want to implement additional logic while declaring a persistent object. For example, it’s possible to define an association between two persistent objects that corresponds to a relationship between target data tables. Or, it’s possible to perform initialization in the object’s constructor, etc. For more information on persistent objects, refer to the XPObject section. For information on attributes supported by XPO, see the Built-In Attributes topic.

Example 1

The following example shows a sample persistent object that represents the Customers table in the standard NorthWind database. Two persistent properties are declared that represent a key CustomerID field and a regular CompanyName field. Both are of the string type. The key CustomerID field is marked with the KeyAttribute attribute:

Table_CustomersTable

using DevExpress.Xpo;

// Represents the Customers data table.
public class Customers : XPLiteObject {
    public Customers(Session session) : base(session) { }
    // Represents the CustomerID key field.
    [Key]
    public string CustomerID {
        get { return fCustomerID; }
        set { SetPropertyValue(nameof(CustomerID), ref fCustomerID, value); }
    }
    string fCustomerID;

    // Represents the CompanyName field.
    public string CompanyName {
        get { return fCompanyName; }
        set { SetPropertyValue(nameof(CompanyName), ref fCompanyName, value); }
    }
    string fCompanyName;

}

Example 2

The following example shows how to change the default mapping using the PersistentAttribute attribute.

In the example, a persistent object is created to represent the “Sales.SalesOrderDetail” table in the AdventureWorks database that ships with MS SQL Server:

Table_Sales_SalesOrderDetail

The problem with creating a persistent object for this table is that the object cannot be named using the compound “Sales.SalesOrderDetail” name. To resolve the problem, the object is named “SalesOrderDetail” and is mapped to the corresponding data table using the PersistentAttribute attribute.

The SalesOrderDetail object declares three persistent properties corresponding to the SalesOrderDetailID, OrderQty and ProductID fields. For demonstration purposes, the field that corresponds to the ProductID field is named “Product” and is mapped to the corresponding data field using the PersistentAttribute attribute:

// Represents the Sales.SalesOrderDetail data table.
[Persistent("Sales.SalesOrderDetail")]
public class SalesOrderDetail : XPLiteObject {
    public SalesOrderDetail(Session session) : base(session) { }
    // Represents the SalesOrderDetailID key field.
    [Key]
    public System.Int32 SalesOrderDetailID {
        get { return fSalesOrderDetailID; }
        set { SetPropertyValue(nameof(SalesOrderDetailID), ref fSalesOrderDetailID, value); }
    }
    System.Int32 fSalesOrderDetailID;

    // Represents the OrderQty field.
    public System.Int16 OrderQty {
        get { return fOrderQty; }
        set { SetPropertyValue(nameof(OrderQty), ref fOrderQty, value); }
    }
    System.Int16 fOrderQty;

    // Represents the ProductID field.
    [Persistent("ProductID")]
    public System.Int16 Product {
        get { return fProduct; }
        set { SetPropertyValue(nameof(Product), ref fProduct, value); }
    }
    System.Int16 fProduct;

}
See Also