一.XPO简介:

XPO即eXpress Persistent Objects for .NET,现在这里介绍的版本是1.5。

XPO在应用程序代码和数据库之间扮演了一个中间层的角色,简单而言,就是将面向对象编程所建立的对象在数据库中做一个映射,使之和数据库中的表建立一一对应的关系。XPO现在的版本已经可以处理对象之间一对多,多对多等关系的处理,继承在数据库中的实现以及根据情况处理进行数据库的并发访问,提高系统的效率。

XPO最大的好处就是可以将应用程序开发者从繁琐的数据库设计中解脱出来,专心建立业务对象系统,如何将这些对象映射到数据库中,这一切都可以交给XPO来自动处理了。
 
二.XPO的简单使用:

XPO的使用十分简单,如果是应用系统的数据关系不复杂,对于应用开发人员而言,根本上可以不了解XPO太深入的技术,只需要在建立对象类过程中,遵循一定的规则就可以了。而且在使用过程中也根本可以不去关心数据库后台发生的事情,例如后台是什么数据库,表到底有多少等。

1.建立对象类:

首先是需要定义对象,一切的对象只需要继承于XPObject即可。

例如下面的代码就是建立一个Member的类,其中涉及到名字和年龄。

这个是一个最简单的例子,在使用过程中根本不需要考虑数据库到底建立了没有,以及数据库建立在那里等。当然,如果在应用中需要了解这些信息,在后面的介绍中可以看到,其实XPO同样提供了十分丰富的函数来获取这些信息的。

using System;
using DevExpress.Xpo;

namespace testXPO
{
     /// <summary>
     /// Member 的摘要说明。
     /// </summary>
     public class Member : XPObject
     {
         public string strName;
         public int iAge;        

         public Member()
         {
              //
              // TODO: 在此处添加构造函数逻辑
              //
         }
     }
}

2.使用和保存这些对象的数据:

以下代码是定义一个Member,并且将这些数据保存起来的例子:

              Member m = new Member();
              m.iAge = 15;
              m.strName = "testName";
              m.Save();

可以看到使用起来十分方便,一点也看不到数据库操作的影子。

3.获取对象的集合信息:

保存的信息如何全部获取呢?以下是个例子:

              foreach (Member m in new XPCollection(typeof(Member)))
              {
                lstResult.Items.Insert(0,"Age:" + m.iAge + "; Name:" + m.strName);
              }

假设将全部Member的信息显示在一个ListBox中。

小结:到此为止对于如何使用XPO应该有个很初步的了解了。

步骤大致如下:

1.  将DevExpress.XPO.dll引用进来;
2.  声明使用 using DevExpress.XPO;;
3.  需要数据保存的类则继承于XPObject;
4.  需要对外的信息则定义成字段即可,一切象一般创造一个类无异;

XPO到底做了些什么呢?

面对这么简单的代码,其实和数据库的互动已经全部由XPO自动帮你完成了。

1.  运行后会在当前目录下建立一个<AppName>.MDB的数据文件;
2.  打开这个数据文件可以发现有两个系统自动建立的表:XPDeletedObject和XPObjectType;
3.  另外还有就是对应类的表了,这里是Member表。

在MDB中的结构如下图所示:

到此为止我们已经可以用XPO来完成新建表,新建记录,返回全部记录这些传统的数据库操作了。虽然功能十分简单,但是可以大致了解XPO大致会为我们做些什么了,会给我们带来一些什么的方便了。

三.XPO的进一步使用:

(一)对象关系的处理:

XPO支持对象之间一对一,一对多和多对多的关系。

1.定义一对多的关系:

假设有一个Student的类和一个Class类是一对多的对应关系,一个学生可以有多个Class的信息。

类图关系如下:

Class类对应的代码:

using System;
using DevExpress.Xpo; 

namespace testXPO
{
     /// <summary>
     /// Class 的摘要说明。
     /// </summary>
     public class Class : XPObject
     {
        [Association("StudentClasses")]
        public Student Student;
        public string Name;
        public int Credit;

        public Class()
        {
              //
              // TODO: 在此处添加构造函数逻辑
              //

         }
     }
}

Student类对应的代码

using System;
using DevExpress.Xpo;

namespace testXPO
{
     /// <summary>
     /// Student 的摘要说明。
     /// </summary>
     public class Student : XPObject
     {
         public string Name;
         public int Age;

        [Association("StudentClasses", typeof(Class))]
        public XPCollection Classes { get { return GetCollection("Classes"); } }
        public Student()
         {
              //
              // TODO: 在此处添加构造函数逻辑
              //
         }
     }
}

其中Association属性部分就是关键定义这个一对多关系的代码。

以下代码是添加记录的代码,假设添加5个学生,每个学生有不同的三门课程。

              for (int i=1;i<6;i++)
              {
                Student sd = new Student();
                sd.Name= "Student" + i.ToString();
                sd.Age = 2*i;
                Class cls1 = new Class();
                Class cls2 = new Class();
                Class cls3 = new Class();
                cls1.Name = sd.Name + "英语";
                cls1.Credit = 5 * sd.Age;                 
                sd.Classes.Add(cls1);
                cls2.Name = sd.Name + "数学";
                cls2.Credit = 6 * sd.Age;
                sd.Classes.Add(cls2);
                cls3.Name = sd.Name + "语文";
                cls3.Credit = 7 * sd.Age;
                sd.Classes.Add(cls3);
                sd.Save();            

              }

可以看出:

Class数据不需要单独保存,在后面总体对Student做一个保存,XPO会自动完成CLASS数据的保存;对于一个学生对应几个CLASS,每个CLASS的实体需要存在,例如这里就新建了cls1-cls3三个不同的实体,否则保存到数据库中,之后最后一个实体有效。
那么在数据库中发生了什么事情呢:

CLASS和STUDENT两个表自动生成了,且数据也保存了,之间的关系也建立了,如下图:

以下是对这种关系的数据进行浏览,例如想获取学分是5的信息:

XPCollection clsAll = new XPCollection(typeof(Class), new BinaryOperator("Credit", 5, BinaryOperatorType.Equal));
foreach (Class cls in clsAll)
     {
         lstResult.Items.Insert(0,"Student's Name: " + cls.Student.Name + 
                ";Student's Age:" + cls.Student.Age + "; Class's Name:" + cls.Name);
     }

由此可见XPCollection可以作为对象的集合来使用,且对应回数据库中的记录概念,当然这种对象的集合比数据表的记录灵活很多。

小结:对于关系,一方的关系定义象Student中:

        [Association("StudentClasses", typeof(Class))]
        public XPCollection Classes { get { return GetCollection("Classes"); } }

而多方中的关系定义象Class中:

        [Association("StudentClasses")]
        public Student Student;

也就是说一方定义需要集合类型(多),而多方定义则只须定义回一方的类。

注意:Association中定义的关系名字是相同的。

(二)对象继承的处理:

继承的例子:例如学校中有Staff和Dean类,Dean从Staff继承过来,当你查找Staff的数据时,Dean的数据也会获取出来的。
 
定义Staff的代码:

using System;
using DevExpress.Xpo;

namespace testXPO
{
     /// <summary>
     /// Staff 的摘要说明。
     /// </summary>
     public class Staff : XPObject
     {
         public string Name;
         public int Age;
        [Association("DeanStaffs")]
        public Dean Dean = null;
        public Staff()
        {
            //
            // TODO: 在此处添加构造函数逻辑
            //
         }
     }
}

定义Dean的代码:

using System;
using DevExpress.Xpo;

namespace testXPO
{
     /// <summary>
     /// Dean 的摘要说明。
     /// </summary>
     public class Dean : Staff
     {
         public string Department;
        [Association("DeanStaffs", typeof(Staff))]
        public XPCollection Staffs 
        {
           get { return GetCollection("Staffs"); }
        }

         public Dean()
         {
              //
              // TODO: 在此处添加构造函数逻辑
              //
         }
     }
}

可见继承关系除了面向对象本身定义了的继承外,还需要声明之间的关系,这个关系就是对应到数据库中的关系了。

以下是生成数据的代码:

              for (int i=1;i<11;i++)
              {
               Dean d = new Dean();
               d.Name = "Dean" + i.ToString();
               d.Age = 100 * i;
               d.Department = "Dean's Department" + i.ToString();
               d.Save();
              }         

              for (int j=1;j<20;j++)
              {
               Staff s = new Staff();
               s.Name = "Staff" + j.ToString();
               s.Age = j;
               s.Save();
              }

前面部分生成Dean的数据,后面生成Staff的数据,那么数据库里面发生了什么变化呢:
生成的数据如下图:

这里可以看到Dean中的OID不再是自动生成的了,而是对应Staff中的OID。

小结:

对于父类,需要声明关系如Staff:

        [Association("DeanStaffs", typeof(Staff))]
        public XPCollection Staffs 
        {
            get { return GetCollection("Staffs"); }
        }

对于子类,需要声明关系如Dean:

        [Association("DeanStaffs")]
        public Dean Dean = null;

(三)XPO中Session的使用:

XPO的缺省设置是使用MS Access OLEDB,并且使用在当前路径下的MDB,如果应用需要特别指明数据库则需要用到Session了。

只需要在对象构造时将Session作为参数传递进去就可以了。

例如:

     public class Member : XPObject
     {
         public string strName;
         public int iAge;      

         public Member(Session session) : base (session)
         {
              //
              // TODO: 在此处添加构造函数逻辑
              //
         }
     }

创建Session则如下面的代码:

Session session2 = new Session();
session2.AutoCreateOptions = AutoCreateOptions.SchemaOnly;
session2.ConnectionString = "Provider=Microsoft.Jet.OLEDB.4.0;
    User ID=Admin;Data source=SessionExample2_cs.mdb;Mode=Share Deny None;";
session2.Connect();

(四)XPO中查询数据:

对于查询,就是指定一定的条件获取一个数据集合。在XPO中,返回结果的集合用XPCollection作统一处理,而条件查询的条件设置,则通过

BinaryOperator来指定。

例如:要查询出生日期在”01/02/1960”年之前的客户资料:

 new XPCollection(typeof(Customer), 
       new BinaryOperator("BirthDate", new DateTime(1960, 1, 2), BinaryOperatorType.Less))

如果条件是组合的,例如:要查询出生日期在”01/02/1960”年之前的且地址是第十大街的顾客的资料:

GroupOperator criteria = new GroupOperator();
criteria.Operands.Add(new BinaryOperator("BirthDate", new DateTime(1960, 1, 2), BinaryOperatorType.Less));
criteria.Operands.Add(new BinaryOperator("Address.Street", "10'th Avenue"));
 new XPCollection(typeof(Customer), criteria)

(五)XPO中的事务处理:

XPO提供了类似于Microsoft ADO.NET中的事务处理,你可以在Session中使用Begin,Commit或者Rollback的方法来完成处理。在当前的版本中,事务处理的嵌套并不支持。

以下代码是事务处理的例子:

class Account: XPObject {
         public double Amount = 0;
         protected override void BeforeSave() {
                 base.BeforeSave();
                 if (Amount < 0) {
                          throw new Exception("Negative amount");
                 }
         }
}

void TransferAmount(double amount) {
         Account account = new Account();
        Session.DefaultSession.BeginTransaction();
         try {
                 account.Amount = amount;
                 account.Save();
               Session.DefaultSession.CommitTransaction();
         }
         catch (Exception e) {
               Session.DefaultSession.RollbackTransaction();
                 account.Reload();
         }
}

(六)XPO中返回记录的分页处理:

在XPO中,除了XPCollection外,还有一个XPCursor提供了一个获取返回记录的另外一种方式。和XPCollection返回全部的满足条件的集合不同,XPCursor根据XPCursor.PageSize的设置依次返回满足条件的每页数据。
 
XPCursor这种特性在处理数据量比较大的表是十分有用的,可以减少每次内存的使用量和减少返回的时间。

当然,每次翻页则需要重新获取数据。

(七)XPO中对结构体的支持:

从1.5版本开始,XPO将支持结构的特性。

例如定义一个圆的类,圆心是一个结构体,代码如下:

using System;
using DevExpress.Xpo;
 

namespace testXPO
{
     /// <summary>
     /// Circle 的摘要说明。
     /// </summary>
     public struct Point 
     {
         [Persistent("Abscissa")]
         public int X;
         public int Y;
     }

     public class Circle : XPObject
     {
         public string Name = "";
         [Persistent("Location")]
         public Point Center;
         public Circle()
         {
              //
              // TODO: 在此处添加构造函数逻辑
              //
         }
     }
}

生成数据的代码如下:

              for (int i=1;i<11;i++)
              {
               Circle c = new Circle();
               c.Name = "Circle" + i.ToString();
               c.Center.X = 100 + i;
               c.Center.Y = 10 + i;
               c.Save();
              }

看看数据库中表的存储情况:


小结:XPO对结构体已经支持,并且将其平面化到同一个表中。

?? 不知道对结构体嵌套的是否支持?有待证实

对于结构体相关数据的查询也并不复杂,例如下面:

 new XPCollection(typeof(Shape), new BinaryOperator("Position.X", 1))

XPO开发指南简要的更多相关文章

  1. DevExpress XPO 开发指南 简要

    最近在看devexpress   安装程序中的代码Demos ..  C:\Users\Public\Documents\DevExpress Demos 16.1\Components\WinFor ...

  2. AngularJS开发指南16:AngularJS构建大型Web应用详解

    AngularJS是由Google创建的一种JS框架,使用它可以扩展应用程序中的HTML功能,从而在web应用程序中使用HTML声明动态内容.在该团队工作的软件工程师Brian Ford近日撰写了一篇 ...

  3. HelloX操作系统网络功能简介及使用和开发指南

    HelloX网络功能简介及使用和开发指南 HelloX网络功能简介 作为物联网操作系统,网络功能是必备的核心功能之一.按照规划,HelloX实现了两个不同类型的TCP/IP协议栈,一个面向资源受限的嵌 ...

  4. HelloX项目github协同开发指南

    概述 为了提高协同开发效率,HelloX项目已托管到github网站上.根据目前的开发进展,创建了下列几个子项目: HelloX操作系统内核项目:https://github.com/hellox-p ...

  5. Jdon框架开发指南

    Jdon框架快速开发指南 开发主要步骤如下: JdonFramework6.0以上两步开发见这里. 快速配置指南 新增/查询/修改/删除(CRUD); 批量查询和分页显示 本文Step By Step ...

  6. 《Apache HttpClient 4.3开发指南》

    转载自:http://blog.csdn.net/chszs/article/details/16854747 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chs ...

  7. ASP.NET Aries 开源开发框架:开发指南(一)

    前言: 上周开源了Aries开发框架后,好多朋友都Download了源码,在运行过程里,有一些共性的问题会问到. 所以本篇打算写一下简单的开发指南,照顾一下不是太看的懂源码的同学,同时也会讲解一下框架 ...

  8. FreeMarker模板开发指南知识点梳理

    freemarker是什么? 有什么用? 怎么用? (问得好,这些都是我想知道的问题) freemarker是什么? FreeMarker 是一款 模板引擎: 即一种基于模板和要改变的数据, 并用来生 ...

  9. Jetty使用教程(四:21-22)—Jetty开发指南

    二十一.嵌入式开发 21.1 Jetty嵌入式开发HelloWorld 本章节将提供一些教程,通过Jetty API快速开发嵌入式代码 21.1.1 下载Jetty的jar包 Jetty目前已经把所有 ...

随机推荐

  1. 防止Form中嵌入WebBrowser出错导致程序崩溃

     siow(1253366)  10:11:13两种方法你用的自带的webbrowser还是embeded那个毛小毛(3335076)  10:12:15或者有什么办法拦截到是webbrowser,如 ...

  2. Writing a Discard Server 写个抛弃服务器 世上最简单的协议

    Netty.docs: User guide for 4.x https://netty.io/wiki/user-guide-for-4.x.html The most simplistic pro ...

  3. devops model

    1,自动部署() 2,在线监控 (可视化,智能化) 3,故障诊断 (故障识别,故障隔离) 4,快速定位 (识别环境与程序,数据等问题) 评测工具开发---- 统计条目增加大项目: BI中权限―拨测数据 ...

  4. Linux系统CPU核数等信息查看

    版权声明:本文为原创文章,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明. https://blog.csdn.net/fgf00/article/details/52584 ...

  5. spring boot 系列学习记录

    ——初始篇 结束了短学期的课程,初步学习了ssm框架,凭借这些学到的知识完成了短学期的任务-----点餐系统. 通过学长了解到了spring boot ,自己对spring cloud有所耳闻,但是s ...

  6. Yii框架2.0的模块

    模块是个独立的软件单元,也是又控制器,视图,模型组成的,也可以有自己的布局.但他必须属于某个应用下,不能独立存在. 其中模块的控制器,视图和应用的控制器和视图使用基本相同,不作赘述,下面说说模块的使用 ...

  7. 关于编译openjdk过程的一个编码错误

    -Xlint:deprecation 重新编译 或者 错误: 编码ascii的不可映射字符 出现这种错误的时候 可以进行设置jdk编译编码即可解决 因为是编译openjdk  所以在环境变量中设置: ...

  8. Newman语法参数

    npm install -g newman npm install -g newman-reporter-html newman run XXX.json -k -r html --reporter- ...

  9. 【IPC进程间通讯之中的一个】邮槽MailSlot

    IPC进程间通信+邮槽MailSlot                IPC(Inter-Process Communication.进程间通信).        现代计算机採用虚拟内存机制,为进程提 ...

  10. python学习笔记(十三)接口开发

    一.开发接口的作用 1.mock接口,模拟一些接口,在别的接口没有开发好的时候,需要开发一些模拟接口进行调试和测试. 2.查看数据,比如,获取所有学员信息的接口,就不需要提供数据库的查看信息. 二.接 ...