程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> XAF應用開發教程(二)業務對象模型之簡單類型屬性,xaf應用開發

XAF應用開發教程(二)業務對象模型之簡單類型屬性,xaf應用開發

編輯:C#入門知識

XAF應用開發教程(二)業務對象模型之簡單類型屬性,xaf應用開發


使用過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.為客戶類填加屬性,填加屬性後將對應著數據庫中的字段:

我將在代碼中依次填加,姓名、禁用、性別、出生日期、手機號碼、地址、年收入、照片,幾個字段。

  1 using System;
  2 using System.Linq;
  3 using System.Text;
  4 using DevExpress.Xpo;
  5 using DevExpress.ExpressApp;
  6 using System.ComponentModel;
  7 using DevExpress.ExpressApp.DC;
  8 using DevExpress.Data.Filtering;
  9 using DevExpress.Persistent.Base;
 10 using System.Collections.Generic;
 11 using System.Drawing;
 12 using DevExpress.ExpressApp.Model;
 13 using DevExpress.Persistent.BaseImpl;
 14 using DevExpress.Persistent.Validation;
 15 
 16 namespace XCRMDemo.Module.BusinessObjects
 17 {
 18     [DefaultClassOptions]
 19     //[ImageName("BO_Contact")]
 20     //[DefaultProperty("DisplayMemberNameForLookupEditorsOfThisType")]
 21     //[DefaultListViewOptions(MasterDetailMode.ListViewOnly, false, NewItemRowPosition.None)]
 22     //[Persistent("DatabaseTableName")]
 23     // Specify more UI options using a declarative approach (https://documentation.devexpress.com/eXpressAppFramework/CustomDocument112701.aspx).
 24     public class 客戶 : BaseObject
 25     {
 26         // Inherit from a different class to provide a custom primary key, concurrency and deletion behavior, etc. (https://documentation.devexpress.com/eXpressAppFramework/CustomDocument113146.aspx).
 27         public 客戶(Session session)
 28             : base(session)
 29         {
 30         }
 31 
 32         public override void AfterConstruction()
 33         {
 34             base.AfterConstruction();
 35             // Place your initialization code here (https://documentation.devexpress.com/eXpressAppFramework/CustomDocument112834.aspx).
 36         }
 37 
 38         //姓名、禁用、性別、出生日期、手機號碼、地址、年收入、照片
 39         private string _姓名;
 40 
 41         public string 姓名
 42         {
 43             get { return _姓名; }
 44             set { SetPropertyValue("姓名", ref _姓名, value); }
 45         }
 46 
 47         private bool _禁用;
 48 
 49         public bool 禁用
 50         {
 51             get { return _禁用; }
 52             set { SetPropertyValue("禁用", ref _禁用, value); }
 53         }
 54 
 55         private 性別 _性別;
 56 
 57         public 性別 性別
 58         {
 59             get { return _性別; }
 60             set { SetPropertyValue("性別", ref _性別, value); }
 61         }
 62 
 63         private DateTime _出生日期;
 64 
 65         public DateTime 出生日期
 66         {
 67             get { return _出生日期; }
 68             set { SetPropertyValue("出生日期", ref _出生日期, value); }
 69         }
 70 
 71         private string _手機號碼;
 72 
 73         public string 手機號碼
 74         {
 75             get { return _手機號碼; }
 76             set { SetPropertyValue("手機號碼", ref _手機號碼, value); }
 77         }
 78 
 79         private string _地址;
 80 
 81         public string 地址
 82         {
 83             get { return _地址; }
 84             set { SetPropertyValue("地址", ref _地址, value); }
 85         }
 86 
 87         private decimal _年收入;
 88 
 89         public decimal 年收入
 90         {
 91             get { return _年收入; }
 92             set { SetPropertyValue("年收入", ref _年收入, value); }
 93         }
 94 
 95 
 96         [Size(SizeAttribute.Unlimited), VisibleInListView(true)]
 97         [ImageEditor(ListViewImageEditorMode = ImageEditorMode.PictureEdit,
 98             DetailViewImageEditorMode = ImageEditorMode.PictureEdit,
 99             ListViewImageEditorCustomHeight = 40)]
100         public byte[] 照片
101         {
102             get { return GetPropertyValue<byte[]>("照片"); }
103             set { SetPropertyValue<byte[]>("照片", value); }
104         }
105     }
106 
107     public enum 性別
108     {
109         男,女,未知
110     }
111 }

代碼修改為上述內容後,我們再次運行系統,按下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 typeAdvantageAsaAseDB2FirebirdMySQLMS AccessMSSQLMSSQL CEOraclePervasive SQLPostgre SQLVistaDB 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 = 40)]
        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群:50185791

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved