How it Works
First of all: Why Should You Use Persistent Objects?
Object-oriented application design and development has proven to be a very efficient and productive way to develop today's complex applications. It increases opportunities for code reuse and gives your more flexibility in the world of ever-changing end-user requirements. When creating database applications, however, developers seem forced to work with tables, views, and data field objects and not directly with business objects, which their application ultimately attempts to model. This gap between the realm of relational database technologies like ADO.NET and domain-specific business objects presents a significant challenge to developers wanting to exercise object-oriented programming. So is there a way to map your well designed business object model to a relational database without having to deal with tables and fields? As you might have guessed by now, the answer is yes: with eXpress Persistent Objects you can. XPO is a fully automated framework that lets you design an arbitrary hierarchy of business objects and takes care of the persistence for you, letting you focus on the functional aspects of your application.
A note on the examples: these have been created in the shortest possible form that still allows to make the point of each piece of sample code. For example, we don't favor the use of public fields in classes, but as it's a lot shorter than the property syntax, we have used them in the sample code in this page.
Example
Let's look at a simple example: A Contact class for a sales management application:
|
public class Contact { public string FirstName; public string LastName; public string PhoneNumber; public string Email; }
Public Class Contact Public FirstName As String Public LastName As String Public PhoneNumber As String Public Email As String End Class
|
Obviously all Contacts for our sales management application should be stored in the database, so Contact must be a persistent object. Making it persistent is easy: all you have to do is inherit it from XPObject:
|
using DevExpress.Xpo; ... public class Contact: XPObject { public string FirstName; public string LastName; public string PhoneNumber; public string Email; }
Imports DevExpress.Xpo ... Public Class Contact : Inherits XPObject Public FirstName As String Public LastName As String Public PhoneNumber As String Public Email As String End Class
|
Now it's already possible to create and save a Contact instance. By default, XPO creates a Microsoft Access compatible database in the same directory where the executable of your application lives. By specifying a default connection string of your own, you can easily change this (see the commented lines). In either case, XPO creates the necessary database structure for you automatically.
|
...
Contact contact = new Contact(); contact.FirstName = "John"; contact.LastName = "Doe"; contact.Email = "jdoe@johndoe.com"; contact.Save(); ...
...
Dim contact As Contact = New Contact() contact.FirstName = "John" contact.LastName = "Doe" contact.Email = "jdoe@johndoe.com" contact.Save ...
|
It is really that simple. The code above will create a Contact table and insert one record into it.
Retrieving Objects from a Database
Of course, it's never enough just to store an object into the database. You will need a way to retrieve objects. In XPO.NET you do this by creating instances of the XPCollection class:
|
XPCollection contacts = new XPCollection(typeof(Contact)); foreach(Contact contact in contacts) { Console.WriteLine(contact.Email); }
Dim contacts As XPCollection = New XPCollection(GetType(Contact)) Dim contact As Contact For Each contact In contacts Console.WriteLine(contact.Email) Next
|
In your sales management application you may need to display a list of contacts in the DataGrid. XPCollection can be a data source for DataGrid (or any other .NET control that works with data binding), because it implements the standard IBindingList interface:
|
contactDataGrid.DataSource = contacts;
contactDataGrid.DataSource = contacts
|
In order to display objects within the DataGrid properly you should specify the desired properties for your collection.
|
contacts.DisplayableProperties = "FirstName;LastName;Email";
contacts.DisplayableProperties = "FirstName;LastName;Email"
|
At times, you don't need all Contact objects from the database, but you need to find some of them based on a given criteria. As you know, database management systems provide efficient ways to search for data, so you can use this feature instead of iterating through all contacts and evaluating each one. Criteria is a tree of objects that represents an expression with simple object-oriented syntax. You don't have to use SQL yourself, XPO does that for you behind the scenes. For example, if you want to find "John Doe", you can use the following code:
|
XPCollection jdoe = new XPCollection(typeof(Contact), new GroupOperator(GroupOperatorType.And, new BinaryOperator("FirstName", "John"), new BinaryOperator("LastName", "Doe")));
Dim jdoe As XPCollection = New XPCollection(GetType(Contact), _ New GroupOperator(GroupOperatorType.And, _ New BinaryOperator("FirstName", "John"), _ New BinaryOperator("LastName", "Doe")))
|
By default, objects in the collection are returned in no particular order. If you want the collection to be sorted, you have to specify sort order:
|
XPCollection jdoe = new XPCollection(typeof(Contact), new BinaryOperator("FirstName", "John"), new SortProperty("LastName", SortingDirection.Ascending);
Dim jdoe As XPCollection = New XPCollection(GetType(Contact), _ New BinaryOperator("FirstName", "John"), _ New SortProperty("LastName", SortingDirection.Ascending))
|
Relationships Between Objects
Usually your business objects won't exist alone. They will have relationships. For instance, your contacts can belong to a company:
|
using DevExpress.Xpo; ... public class Company : XPObject { public string Name; public string PhoneNumber; public string WebSite; }
public class Contact : XPObject { public string FirstName; public string LastName; public string PhoneNumber; public string Email; public Company Employer; }
Imports DevExpress.Xpo ... Public Class Company : Inherits XPObject Public Name As String Public PhoneNumber As String Public WebSite As String End Class
Public Class Contact : Inherits XPObject Public FirstName As String Public LastName As String Public PhoneNumber As String Public Email As String Public Employer As Company End Class
|
You may wonder what you have to do to implement persistence in this case. The answer is: nothing! XPO understands that the property Employer is a reference to another business object, so it will preserve this reference in its database structure. Sometimes your business objects will have child objects. For example, an Order object might contain several OrderLine instances. In this case you need to give XPO a hint about the type of objects that are going to be stored in this collection. This is done with the AssociationAttribute:
|
using DevExpress.Xpo; ... public class OrderLine : XPObject { public string Description; public double Price; public int Quantity; [Association("OrderLines")] public Order Order; }
public class Order : XPObject { public string OrderNo; public string Description;
[Aggregated, Association("OrderLines", typeof(OrderLine))] public XPCollection OrderLines { get { return GetCollection("OrderLines"); } } }
Imports DevExpress.Xpo ... Public Class OrderLine : Inherits XPObject Public Description As String Public Price As Double Public Quantity As Integer <Association("OrderLines")> _ Public Order As Order End Class
Public Class Order : Inherits XPObject Public OrderNo As String Public Description As String
<Association("OrderLines", GetType(OrderLine)), Aggregated()> _ Public ReadOnly Property OrderLines() As XPCollection Get Return GetCollection("OrderLines") End Get End Property End Class
|
Object Identification
Object variables let you reference objects in a program. But persistent objects need to maintain their unique identities even when they are currently in storage and not instantiated in a running application. For this purpose, every persistent object includes an Oid (object identifier) property, which uniquely identifies the object. By default, an Int32 is used for this, so the identification is valid only within object instances of a particular class. Although it's not a part of this introductory description, other data types can easily be used as object identifiers. This example shows you how to retrieve object using a previously stored Oid:
|
Contact contact = (Contact)Session.DefaultSession.GetObjectByKey(typeof(Contact), storedOid);
Dim contact As Contact = CType(Session.DefaultSession.GetObjectByKey(GetType(Contact), storedOid), Contact)
|
As these simple examples show, XPO allows you to use object-oriented techniques to create and implement your business objects while having an easy-to-use persistence layer provide the storage functionality for you. No database specific code needs to be written, which simplifies work for the developers and makes applications more flexible and reusable: the same code will work in a simple desktop application with MDB (Microsoft Access) files or in a large SQL Server based server farm. |
Subscribe Today
General Information
Feature Details
XPO-Based Frameworks
eXpressApp Framework (XAF)
Need to quickly get DevExpress presentation and data access components seamlessly integrated together for a data centric Microsoft Office inspired desktop or web application? Try XAF - a modern and flexible business application framework that facilitates a plug and play approach to common business requirements such as data validation, security and reporting.
 
An XPO Data Model in XAF
eXpand Framework
An open source community-driven toolkit built above XAF and XPO to extend their capabilities and provide 50+ cutting-edge libraries containing tools and reusable modules that target numerous business scenarios.
Our Awards
|