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

对于初学者来说,这里边的代码可能会被忽略,但还是必须来看看的,cs下边有很多简单的demo ,  在学习的过程中,可以看到以前从未了解的一些知识点.

devexpress 是个功能强大的控件集合,深入下去, 知识量还是满大的. 今天就说说这个xpo ,在cs下ContactManagement 这个文件夹下.打开项目就可以看了.

一.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))

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

  1. XPO开发指南简要

    一.XPO简介: XPO即eXpress Persistent Objects for .NET,现在这里介绍的版本是1.5. XPO在应用程序代码和数据库之间扮演了一个中间层的角色,简单而言,就是将 ...

  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. Delphi 不使用自带模板创建服务

    program Project1; uses Windows, WinSvc; const ServiceName: pchar = 'SnowWings Service'; DisplayName: ...

  2. UI简单工作

     UI用户界面 需求——效果图——风格设计——高保证效果——html 网页的宽度=屏幕的宽度-纵向滚动条的宽度 企业网站一般是1280 根据百度流量研究所 目前我们的网页注主要是1024和1200   ...

  3. freemarker取数

    在后端map必须的键值必须是字符串 java.util.Map busVoltagesMap = new java.util.HashMap(); busVoltagesMap.put("1 ...

  4. 吴裕雄 python 爬虫(3)

    import hashlib md5 = hashlib.md5() md5.update(b'Test String') print(md5.hexdigest()) import hashlib ...

  5. HTTPConnectionPool(host:XX)Max retries exceeded with url

    爬虫多次访问同一个网站一段时间后会出现错误 HTTPConnectionPool(host:XX)Max retries exceeded with url '<requests.package ...

  6. hdu2421-Deciphering Password-(欧拉筛+唯一分解定理+积性函数+立方求和公式)

    Deciphering Password Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  7. webstocket 聊天

    /** * 初始化socket **/ function initSocket(index_host){//端口号 if( !window.WebSocket ){ console.log(" ...

  8. SpringMVC点滴(1)

    在使用springMVC很久,却一直没有总结其中的一些便捷配置和功能,恰好有空,加以总结 Servlet 3之后,在web.xml中加入async的支持,从而实现异步请求,需要在servlet和fil ...

  9. C#单例和Unity单例

    单例是一种设计模式 单例:不管在项目中的任何模块,当需要使用某个对象的时候,获取到的始终是同一个对象 在C#中 public class InstanceDemo{ private static In ...

  10. sqlmap自动注入

    基于python2.7开发 git clone https://github.com/sqlmapproject/sqlmap.git sqlmap-dev