物件導向的應用程式設計與開發為當前的複雜應用開發提供了一個高效能與多產的手段,提高了代碼重用的機會,以及當終端使用者需求發生變化時更高的靈活性。 當建立一個資料庫應用時,開發人員看起來總是被迫與資料表、視圖、資料欄位對象打交道,而不是直接處理商業對象。這種關聯式資料庫對象領域的差距現象類似於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); |
|