DevExpress Persistent Object v.1.5

邬弘化
2023-12-01

面向对象的应用程序设计与开发为当前的复杂应用开发提供了一个高性能与多产的手段,提高了代码重用的机会,以及当最终用户需求发生变化时更高的灵活性。

当创建一个数据库应用时,开发人员看起来总是被迫与数据表、视图、数据字段对象打交道,而不是直接处理商业对象。这种关系数据库对象领域的差距现象类似于ADO.NET和特定领域内的商业对象的差别,对开发人员来讲,同样是一极大的挑战。

Visual Studio .NET试图通过类型安全数据集来解决这个问题:一个开发人员可以拾取一个数据表并且生成一个类型安全的数据集类,使该类看上去更类似于一个事务域中的商业对象,这种机制被用于实现持久性商业对象,尽管看来此类对象更像是面向数据的一个结构。

那么有没有一种方法可以映射你设计良好的商业对象模型到关系数据库而不必处理数据表与字段呢?也许您已经猜到这个答案了。通过XPO就要以实现这样的工作。XPO从另外一个不同的角度试图来解决这个问题——通过对商业对象世界的透视。

来看一个小例子。在一个销售管理应用程序中,一个联系人的类是如下来表示的:

 
public class Contact {
      public string FirstName;
      public string LastName;
      public string PhoneNumber;
      public string Email; 
   }

很显然,在销售管理应用系统当中所有的联系人都应该保存在数据库中,因此Contact必然是一个持久化对象。要想将其持久化,其实非常之简单,所需要做的只是将其从XPObject中进行继承:

 
using DevExpress.Xpo;
    ...
    public class Contact: XPObject {
       public string FirstName;
       public string LastName;
       public string PhoneNumber;
       public string Email;
    }

一般在使用持久化对象之前,都要指定一个联接字符串连接到数据库,类似下面的代码:

 
...
    Session.DefaultSession.ConnectionString="...";
    Contact contact = new Contact();
    contact.FirstName = "John";
    contact.LastName =  "Doe";
    contact.Email = "jdoe@johndoe.com";
    contact.Save();
    ...

通过以上如此简单的代码,就在.NET环境中创建了一个Contact表,并且插入一个记录到里面。

那么如何从数据库中取用该对象呢?XPO.NET提供了提供了XPCollection来取用对象:

 
XPCollection contacts = new XPCollection(typeof(Contact));
    foreach(Contact contact in contacts) {
      Console.WriteLine(contact.Email);
    }

比较幸运的是,XPCollection可以作为DataGrid的数据源用以在DataGrid当中显示Contect列表:

 
contactDataGrid.DataSource = contacts;

如果想更改显示对象在DataGrid中的显示项目,可以对Contact.DisplayableProperties进行设置:

 
contacts.DisplayableProperties = "FirstName;LastName;Email";

大多数时候,并不需要从数据库中取用全部的Contact对象,而实际情况往往是按照一定的标准查找部分对象,数据库管理系统往往提供SQL查询来完成这类任务,完全可以用来代替foreach叠代:

 
XPCollection jdoe = new XPCollection(typeof(Contact), 
	new GroupOperator(GroupOperatorType.And,
	new BinaryOperator("FirstName", "John"),
	new BinaryOperator("LastName", "Doe")));

以上代码即查找"John Doe"对象,类似于数据库中的SQL查询语句。

缺省情况下,容器中的对象是无序的,以下代码即取用FirstName="John"并且LastName按照升序进行排序。

 
XPCollection jdoe = new XPCollection(typeof(Contact),  
      new BinaryOperator("FirstName", "John"),
      new SortProperty("LastName", SortingDirection.Ascending);

在绝大部分的商业模型中,数据表都不是独立存在的,表与表之间大都存在着这样那样的关系,比如,联系人往往属于某一间公司:

 
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;
}

在数据表存在关系的情况下,XPO.NET会知道Employer属性是另外一个商业对象的引用,因而会在数据库结构中自动地维护这种关系的存在,而勿需任何手工代码来实现。

如果一个商业对象拥有子对象,比如,一个Order订单一般情况下会有若干个订单细项,这时需要给XPO.NET一个小小的“提示”,告诉它子对象将会被存储在容器当中:

 
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")]  
  public XPCollection OrderLines {
    get { return GetCollection("OrderLines"); }
  }
}

对象变量允许我们在程序当中进行引用,但是在程序程序运行过程中它并非是唯一存在的,因而需要在程序运行过程当中用一个唯一指示符标识出该对象来。在每一个持久性对象当中都有一个OID属性,OID标识某个指定类的唯一标识符:

 
Contact contact = (Contact)Session.DefaultSession.GetObjectByKey(typeof(Contact), storedOID);

通过以上的例子可以看出XPO.NET商业模型与数据表之间的透明转换,即现在开发领域讨论的比较热烈的Object-Relational Mapping,大大提高了商业的重用性和灵活性,实现了面向对象的数据库编程。在功能与Borland公司提出的ECO(Enterprise Core Object)模型非常类似,当然XPO.NET的对于数据库的连接日前只实现了SQL和Access的MDB,没办法与ECO的强大所比拟,但是使用VS.NET环境编程的朋友们,如果没办法享受C# Builder(Delphi8.NET)所提供的ECO强大魅力的情况下,使用XPO.NET是当前比较理想的选择,将编程人员的重复复杂的O/R映像关系工作中解放出来,将更我的心思应用到商业模型的实现当中。

 
 类似资料: