使用过ORM的朋友对这一部分理解起来会非常快,如果没有请自行补习吧:D.

不说废话,首先,我们来开发一个简单的CRM系统,CRM系统第一个信息当然是客户信息。我们只做个简单 的客户信息来了解一下XAF好了。

新建项之后,可以看到如下代码界面:

using System;
using System.Linq;
using System.Text;
using DevExpress.Xpo;
using DevExpress.ExpressApp;
using System.ComponentModel;
using DevExpress.ExpressApp.DC;
using DevExpress.Data.Filtering;
using DevExpress.Persistent.Base;
using System.Collections.Generic;
using DevExpress.ExpressApp.Model;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation; namespace XCRMDemo.Module.BusinessObjects
{
[DefaultClassOptions]
//[ImageName("BO_Contact")]
//[DefaultProperty("DisplayMemberNameForLookupEditorsOfThisType")]
//[DefaultListViewOptions(MasterDetailMode.ListViewOnly, false, NewItemRowPosition.None)]
//[Persistent("DatabaseTableName")]
// Specify more UI options using a declarative approach (https://documentation.devexpress.com/eXpressAppFramework/CustomDocument112701.aspx).
public class 客户 : BaseObject
{ // Inherit from a different class to provide a custom primary key, concurrency and deletion behavior, etc. (https://documentation.devexpress.com/eXpressAppFramework/CustomDocument113146.aspx).
public 客户(Session session)
: base(session)
{
}
public override void AfterConstruction()
{
base.AfterConstruction();
// Place your initialization code here (https://documentation.devexpress.com/eXpressAppFramework/CustomDocument112834.aspx).
}
//private string _PersistentProperty;
//[XafDisplayName("My display name"), ToolTip("My hint message")]
//[ModelDefault("EditMask", "(000)-00"), Index(0), VisibleInListView(false)]
//[Persistent("DatabaseColumnName"), RuleRequiredField(DefaultContexts.Save)]
//public string PersistentProperty {
// get { return _PersistentProperty; }
// set { SetPropertyValue("PersistentProperty", ref _PersistentProperty, value); }
//} //[Action(Caption = "My UI Action", ConfirmationMessage = "Are you sure?", ImageName = "Attention", AutoCommit = true)]
//public void ActionMethod() {
// // Trigger a custom business logic for the current record in the UI (https://documentation.devexpress.com/eXpressAppFramework/CustomDocument112619.aspx).
// this.PersistentProperty = "Paid";
//}
}
}

1.为客户类填加属性,填加属性后将对应着数据库中的字段:

我将在代码中依次填加,姓名、禁用、性别、出生日期、手机号码、地址、年收入、照片,几个字段。

 using System;
using System.Linq;
using System.Text;
using DevExpress.Xpo;
using DevExpress.ExpressApp;
using System.ComponentModel;
using DevExpress.ExpressApp.DC;
using DevExpress.Data.Filtering;
using DevExpress.Persistent.Base;
using System.Collections.Generic;
using System.Drawing;
using DevExpress.ExpressApp.Model;
using DevExpress.Persistent.BaseImpl;
using DevExpress.Persistent.Validation; namespace XCRMDemo.Module.BusinessObjects
{
[DefaultClassOptions]
//[ImageName("BO_Contact")]
//[DefaultProperty("DisplayMemberNameForLookupEditorsOfThisType")]
//[DefaultListViewOptions(MasterDetailMode.ListViewOnly, false, NewItemRowPosition.None)]
//[Persistent("DatabaseTableName")]
// Specify more UI options using a declarative approach (https://documentation.devexpress.com/eXpressAppFramework/CustomDocument112701.aspx).
public class 客户 : BaseObject
{
// Inherit from a different class to provide a custom primary key, concurrency and deletion behavior, etc. (https://documentation.devexpress.com/eXpressAppFramework/CustomDocument113146.aspx).
public 客户(Session session)
: base(session)
{
} public override void AfterConstruction()
{
base.AfterConstruction();
// Place your initialization code here (https://documentation.devexpress.com/eXpressAppFramework/CustomDocument112834.aspx).
} //姓名、禁用、性别、出生日期、手机号码、地址、年收入、照片
private string _姓名; public string 姓名
{
get { return _姓名; }
set { SetPropertyValue("姓名", ref _姓名, value); }
} private bool _禁用; public bool 禁用
{
get { return _禁用; }
set { SetPropertyValue("禁用", ref _禁用, value); }
} private 性别 _性别; public 性别 性别
{
get { return _性别; }
set { SetPropertyValue("性别", ref _性别, value); }
} private DateTime _出生日期; public DateTime 出生日期
{
get { return _出生日期; }
set { SetPropertyValue("出生日期", ref _出生日期, value); }
} private string _手机号码; public string 手机号码
{
get { return _手机号码; }
set { SetPropertyValue("手机号码", ref _手机号码, value); }
} private string _地址; public string 地址
{
get { return _地址; }
set { SetPropertyValue("地址", ref _地址, value); }
} private decimal _年收入; public decimal 年收入
{
get { return _年收入; }
set { SetPropertyValue("年收入", ref _年收入, value); }
} [Size(SizeAttribute.Unlimited), VisibleInListView(true)]
[ImageEditor(ListViewImageEditorMode = ImageEditorMode.PictureEdit,
DetailViewImageEditorMode = ImageEditorMode.PictureEdit,
ListViewImageEditorCustomHeight = )]
public byte[] 照片
{
get { return GetPropertyValue<byte[]>("照片"); }
set { SetPropertyValue<byte[]>("照片", value); }
}
} public enum 性别
{
男,女,未知
}
}

代码修改为上述内容后,我们再次运行系统,按下F5.

可以看到,我们新建的业务对象“客户”已经在菜中显示了,按下New按钮后,可以看到详细界面。

上面就是新建客户信息的界面了。下面我们来分析一下原理:

在代码中,我们使用了ORM工具,XPO定义了一个客户类,XPO运行时,分根据代码中的属性创建出数据库字段,下图是数据库中的表情况:

可以看出,xpo自动为我们建立了“客户”表,字段与“客户”类中的属性是一一对应的,但Oid,OptimisticLockField,GCRecord三个字段是我们没有建立的属性,却出现了,其中:

Oid,是GUID类型,主键,这是因为我们的代码中是这样写的:

public class 客户 : BaseObject

Oid是在BaseObject中定义的,所以客户类会自动建立这个字段。

OptimisticLockField:是XAF为了解决并发冲突而建立的字段。

GCRecord:继承自BaseObject的类在删除记录时只是逻辑删除,即只是将GCRecord中记录一个值,而没有删除的记录则为Null.
属性的写法:

最简单的,当我们想在数据库中定义一个字段时,可以在xpo类中写一个属性,当然这种说法很肤浅,但是为了方便理解,刚开始时这样认为就可以了。
 39         private string _姓名;
40
41 public string 姓名
42 {
43 get { return _姓名; }
44 set { SetPropertyValue("姓名", ref _姓名, value); }
45 }
这个属性和以往开发中的方法没有什么大的不同,仅是在set部分调用了SetPropertyValue方法,xpo为我们提供了一系列基类,SetPropertyValue是多数类中都有的,它的功能是可以在有值被设置时,需要得到属性变化时可以及时的得到通知。
当然,也可以直接使用
public string 姓名{get;set;}
这样来定义出姓名属性,但是有些场景时却会带来麻烦。
如:
public int 数量{get;set;}
public int 价格{get;set;}
public int 总价{get{return 数量*价格;}}
在数量和价格发生变化时,我们却看不到总价发生变化,因为控件不知道数量、价格已经变化了。所以我们应该尽量使用SetPropertyValue进行写set. 可以看到,字符串类型的姓名,在界面上最终显示成了一个文本框,XAF中内置了很多这样的控件,与类型做出了对应关系,当我们使用对应的类型时,就会自动使用对应的控件,这里的控件被叫做编辑器(PropertyEditor)。 接下来,有禁用属性:
        private bool _禁用;

        public bool 禁用
{
get { return _禁用; }
set { SetPropertyValue("禁用", ref _禁用, value); }
}

同样的,在视图中可以看到一个CheckBox编辑器出现了。

  private DateTime _出生日期;

        public DateTime 出生日期
{
get { return _出生日期; }
set { SetPropertyValue("出生日期", ref _出生日期, value); }
}

DateTime类型,直接使用CLR类型Datetime,日期型字段将在数据库中创建。

可以看出,xpo使用clr类型映射到了数据中字段的类型,下表中说明了数据库表中的字段类型与CLR类型的对应关系:

字段映射

除了自动建立的3个字段外,别的字段都是与代码有对应关系的映射了,xpo默认支持以下几种类型的映射:

C# System data type Advantage Asa Ase DB2 Firebird MySQL MS Access MSSQL MSSQL CE Oracle Pervasive SQL Postgre SQL VistaDB
System.Boolean logical bit bit char(1) char(1) bit bit bit bit number(1,0) bit bool Bit
System.Byte short tinyint tinyint smallint numeric(3,0) tinyint unsigned byte tinyint tinyint number(3,0) smallint smallint Int
System.SByte short numeric(3,0) numeric(3,0) numeric(3,0) numeric(3,0) tinyint short numeric(3,0) numeric(3,0) number(3,0) numeric(3,0) smallint SmallInt
System.Char char(1) char(1) nchar(1) char(1) char CHARACTER SET UNICODE_FSS char char(1) nchar(1) nchar(1) nchar char(1) char(1) NChar
System.Decimal money money money decimal(28,4) decimal(18,4) double currency money numeric(19,4) number(19,5) decimal(20,4) decimal(28,8) Decimal
System.Double double double precision double precision double precision double precision double double double precision float double precision double double precision Float
System.Single double float float float float real single float real float real real Float
System.Int16 short smallint smallint smallint smallint smallint short smallint smallint number(5,0) smallint smallint SmallInt
System.UInt16 integer numeric(5,0) numeric(5,0) numeric(5,0) numeric(5,0) smallint unsigned int numeric(5,0) numeric(5,0) number(5,0) numeric(5,0) numeric(5,0) Int
System.Int32 integer int numeric(10,0) int integer int int int int int integer int Int
System.UInt32 money numeric(10,0) numeric(10,0) numeric(10,0) numeric(10,0) int unsigned decimal(10,0) numeric(10,0) numeric(10,0) numeric(10,0) numeric(10,0) numeric(10,0) BigInt
System.Int64 money bigint numeric(20,0) bigint bigint bigint decimal(20,0) bigint bigint number(20,0) bigint bigint BigInt
System.UInt64 money numeric(20,0) numeric(20,0) numeric(20,0) numeric(18,0) bigint unsigned decimal(20,0) numeric(20,0) numeric(20,0) number(20,0) numeric(20,0) numeric(20,0) BigInt
System.Guid char(36) UNIQUEIDENTIFIERSTR char(36) char(36) char(36) char(38) guid uniqueidentifier uniqueidentifier char(36) char(36) char(36) UniqueIdentifier
System.Enum underlying type underlying type underlying type underlying type underlying type underlying type underlying type underlying type underlying type underlying type underlying type underlying type underlying type
System.String char varchar nvarchar varchar char varying varchar varchar nvarchar nvarchar nvarchar2 varchar varchar NVarChar
System.DateTime timestamp datetime datetime timestamp timestamp datetime datetime datetime datetime date timestamp timestamp DateTime
System.TimeSpan double double precision double precision double precision double precision double double double precision float double precision double double precision Float
System.Byte[] blob image image blob blob LONGBLOB longbinary image, in SQL Server
versions prior to 2005;
otherwise - varbinary
image blob longvarbinary bytea VarBinary
Unlimited size string memo text text clob BLOB SUB_TYPE TEXT longtext LONGTEXT ntext, in SQL Server
versions prior to 2005;
otherwise - nvarchar
ntext nclob longvarchar text NText
 

上面所描述的是都简单类型,其中枚举类型、图像类型、颜色,相对特殊一些,例如枚举类型:

在代码中,我们可以看到如下属性定义
 55         private 性别 _性别;
56
57 public 性别 性别
58 {
59 get { return _性别; }
60 set { SetPropertyValue("性别", ref _性别, value); }
61 }
这里的性别是一个枚举类型,定义如下:
107     public enum 性别
108 {
109 男,女,未知
110 }
打开详细视图,运行效果如下:


可以看出,XAF为我们使用类型进行了推导,自动使用了下拉框,并且取得到了枚举中有哪些值,显示在列表中供我们选择。XAF中的这种自动机制使用得非常多,后续我们将会看到。

图片的存储:
[Size(SizeAttribute.Unlimited), VisibleInListView(true)]
[ImageEditor(ListViewImageEditorMode = ImageEditorMode.PictureEdit,
DetailViewImageEditorMode = ImageEditorMode.PictureEdit,
ListViewImageEditorCustomHeight = )]
public byte[] 照片
{
get { return GetPropertyValue<byte[]>("照片"); }
set { SetPropertyValue<byte[]>("照片", value); }
}

图片的存储稍微有些不一样,在属性的get方法中,使用了GetPropertyValue<byte[]>来取值。

并且使用了几种Attribute,Attribute是为了扩展元数据的描述信息,简单来说,C#(.net)下面的语言不可能是无止境扩展的,所以提供了这样一种特殊的类,可以用来修饰程序中的无素,如assembly,class,interface,property,field,method等 等 .

xpo+xaf定义了很多的Attribute用来描述和扩展元数据信息,其中:

Size(SizeAttribute.Unlimited) 的意义是,创建数据库字段时,长度不限。SizeAttribute.Unlimited的值其实是-1,当然有些场景会用到限制长度。如

[Size(100)] //姓名字段数据库类型将是nvarchar(100)

public string 姓名{......}

[ImageEditor(ListViewImageEditorMode = ImageEditorMode.PictureEdit, DetailViewImageEditorMode = ImageEditorMode.PictureEdit,ListViewImageEditorCustomHeight = 40)]
这里设置了图像所使用的编辑器的参数,列表下面如何显示,详细视图下面如何显示,列表上显示时控制高度。 因为本节主要介绍业务对象的创建方法,不扩展讨论Attribute的用法,后续章节详细描述。 下节介绍几种常见的关系型数据库节构在ORM中的实现方法。
文章示例项目源码下载

QQ:4603528 QQ群:336090194

XAF应用开发教程(二)业务对象模型之简单类型属性的更多相关文章

  1. XAF应用开发教程(三)业务对象模型之引用类型与关联关系

    本节介绍信息系统开发中最常见的问题,引用关系,一对多关系,多对多关系. 以客户信息为例,客户通常需要客户分类,如VIP客户,普通客户,潜在客户.当然,我们可以定义枚举类型进行定义出这个类型,并在客户类 ...

  2. MIP开发教程(二) 使用MIP-CLI工具调试MIP网页

    初始化 MIP 配置 新建一个 MIP 网页 编写 MIP 网页代码 校验 MIP 网页 调试 MIP 网页 1. 初始化 MIP 配置 首先在html目录下进行初始化 MIP 配置: $ mip i ...

  3. 公众号第三方平台开发 教程二 component_verify_ticket和accessToken的获取

    公众号第三方平台开发 教程一 创建公众号第三方平台 公众号第三方平台开发 教程二 component_verify_ticket和accessToken的获取 公众号第三方平台开发 教程三 微信公众号 ...

  4. XAF应用开发教程-内置Attribute功能列表

    在 XAF 框架,一些用来生成一个业务应用程序的信息是在Attribute中指定.您可以将属性应用到业务类 (或它的成员) 指定验证规则,指定如何对数据进行显示. 设置关系类等.本主题提供了有关在何处 ...

  5. XAF应用开发教程(七)外观控制模块

    很多时候,我们需要按照不同的条件显示不同的效果,在传统的软件开发中,我们会直接使用 控件名称.BackColor,Enable,Visible等属性进行控制. 如果一个业务对象在多处使用,要么我们会去 ...

  6. XAF应用开发教程(六)控制器

    是的,XAF也是MVC结构的,但不仅限于MVC,ViewModel也存在,它是一项复合技术,AOP,ORM,MVC都有. 真实运行的系统中,仅有增删改查功能肯定是远远不够的,ERP.CRM等系统的开发 ...

  7. XAF应用开发教程(四)应用程序模型

    XAF是重量型框架,确实够重量的,方方面面都做得规规矩矩. 如果看了前面三节,可能会认为,这N多的Attribute到底都是从哪里来的?到底有多少这样的Attribute?如果不够用了怎么办?等着官方 ...

  8. XAF应用开发教程(一) 创建项目

    XAF是DevExpress公司的快速开发框架,全称eXpress Application Framework,是企业信息系统的开发利器,快速开发效果显著,在.net框架中,笔者至今没有找到一款可以与 ...

  9. XAF应用开发教程(八) 汉化与多国语言支持

    使用了XAF开发时,汉化是一个比较常的问题. 要实现汉化很简单: 1.在这里下载汉化资源文件.这里演示的版本是15.1.X的 2.文件下载后将:文件解压到目录    <你的项目>\BIN\ ...

随机推荐

  1. Github上PHP资源汇总大全,php学习的好资料

    Github上PHP资源汇总大全,php学习的好资料 国外程序员ziadoz 在Github上收集整理了PHP的各种资源,内容包括模板.框架.数据库.安全等方面的库和工具.汇总了各种PHP资源,供各位 ...

  2. href="#"会导致location.replace(location.href);脚本不工作

    我们经常这样:<a onclick="xxx" href="#" 其实这不是一个好习惯,当点下这个连接后,主页面的URL后面会加个#号,这样就会导致很多J ...

  3. How To Set Up vsftpd on CentOS 6

    About vsftpd 警告:FTP是天生不安全.如果你必须使用FTP,考虑securing your FTP connection with SSL/TLS.否则,最好use SFTP, a se ...

  4. ASP开发入门+实战电子书共50本 —下载目录

    小弟为大家整理50个ASP电子书籍,有入门,也有实战电子书,做成了一个下载目录,欢迎大家下载. 资源名称 资源地址 ASP.NET开发实战1200例_第I卷 http://down.51cto.com ...

  5. Centos修改镜像为国内的163源

    一.yum 简介    yum,是Yellow dog Updater, Modified 的简称,是杜克大学为了提高RPM 软件包安装性而开发的一种软件包管理器.起初是由yellow dog 这一发 ...

  6. css弹性盒子学习

    css3弹性盒子是一种布局方式,在适应不同的屏幕大小的时候,能够确保元素拥有更恰当的排布行为.它只是视觉呈现上的,即显示顺序适应显示空间,与源代码无关,源代码顺序不受影响. 定义一个弹性盒子: 在cs ...

  7. Http Basic认证

    Http Basic认证就是访问的时候把用户名和密码用base64加密放在request的header的authorization中 服务端直接获取authorization,解析,跟用户名匹配即可. ...

  8. css3 简单动画

    <script> <!-- var x,y,n=0,ny=0,rotINT,rotYINT function rotateDIV() { x=document.getElementB ...

  9. 20150625_Andriod_02_ListView2_多条目显示_选中

    android listview 参考地址: http://www.cnblogs.com/zhengbeibei/archive/2013/05/14/3078805.html  http://xy ...

  10. 20150612_Andriod contextual action mode 菜单

    参考地址:http://www.xuebuyuan.com/1114028.html              http://www.cnblogs.com/mengdd/p/3564782.html ...