介紹一下我開發的orm框架

iDotNetSpace發表於2009-10-27

前言

最近園子整天為了不是技術的東西在討論,我就調節一下氣氛。介紹一下我開發的ORM框架。還有基本的實現原理。

條條大路通羅馬,原始碼等就不公開了,還是那句,思想才是最重要的。

程式碼例子

實體類的設計

只要繼承了OrmBase,就實現了orm操作,不需要寫任何的配置檔案

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gt    public class OrmUser : OrmBase
    {
        
string userName;
        OrmRole temprole;
        List
<string> addresses;
        List
<OrmRole> roleList;


        [OrmPrimaryKey]
        
public string UserName
        {
            
get { return userName; }
            
set { userName = value; }
        }
        
public OrmRole Temprole
        {
            
get { return temprole; }
            
set { temprole = value; }
        }
        
public List<string> Addresses
        {
            
get { return addresses; }
            
set { addresses = value; }
        }
        
public List<OrmRole> RoleList
        {
            
get { return roleList; }
            
set { roleList = value; }
        }
    }
    
public class OrmRole : OrmBase
    {
        
string name;
        
public string Name
        {
            
get { return name; }
            
set { name = value; }
        }
    }

目前支援了所有的值型別,還有string型別,自定義的class,List型別,Array型別;至於Dictionary其他的不是很通用我就不支援了。

 

部署過程

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gtOrmManager.Schema.Commit<OrmUser>(config);

只要操作Commit,就可以把ORM對映到資料庫,至於怎麼對映的,這個不是使用者考慮的,因此我的ORM操作起來非常的順手。沒有任何多餘的程式碼、多餘的配置。

 

普通呼叫過程

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gtfor (int i = 0; i < 100; i++)
{

    OrmUser user 
= new OrmUser();

    user.UserName 
= "helloworld" + i;

    OrmRole role 
= new OrmRole();

    role.Name 
= "role" + i;
}

過程中,每一步包括建立、賦值都已經直接操作了資料庫,所以我的orm和普通的OO程式碼沒有任何區別。

但是這樣呼叫效能是很低的,每次賦值都會插入資料庫,因此,我提供了快取功能。

 

快取操作

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gtIOrmBufferion buffer = OrmManager.Instance.Bufferion;

for (int i = 0; i < 100; i++)
{
    OrmUser user 
= buffer.Create<OrmUser>();

    user.UserName 
= "helloworld" + i;

    OrmRole role 
= buffer.Create<OrmRole>();

    role.Name 
= "role" + i;
}

buffer.Commit();

如果使用了快取,那麼在Commit之前,所有操作都在記憶體,這樣極大的提高了速度!

當然,在commit裡面使用了一定的優化演算法,比如合併同類資料等等,減少運算元據庫的次數。

ORM的關鍵——查詢問題

ORM是否成功,關鍵就是查詢的實現,我自己編寫了一套物件導向的查詢語法,非常的簡單(不要和Hibernate的HQL對比哦)

先展示一個簡單的查詢例子

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gtUser user = OrmManager.Instance.Query.SelectByUpk<User>("REBORNZHANG@GMAIL.COM");
IOrmRightQuery query 
= OrmManager.Instance.RightQuery;
query.Obj 
= user;
query.Position 
= "USER.ROLELIST";
List
<OrmRole> list = query.SelectRole>();

這個是向右查詢。意思是:我知道了User的物件,想查詢他的RoleList的所有值。

使用起來顧名思義,所以我的查詢語法是非常簡單的,就是【物件】的【屬性】的【屬性】,

例如User有個屬性ROleList,那麼查詢就是User.RoleList。

 

複雜的向右查詢

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gtIOrmRightQuery query = OrmManager.Instance.RightQuery;

query.Position 
= "user.roleList.Permission.ResList.Value = :VALUE";

query.Paras.Add(
"VALUE", resName);

return query.Select<string>().Count > 0;

這個查詢是我的許可權框架裡面經常用到的,就是查詢:

當前使用者的 角色列表裡面的 授權專案裡面的 資源名 是否包含輸入的資源resName

User         RoleList           Permission      ResList.Value

絕對的顧名思義,估計什麼人都很快上手的。

 

向左查詢例項

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gtIOrmLeftQuery query = OrmManager.Instance.LeftQuery;
query.Condition 
= "PROJECTNAME = :PROJECTNAME AND STATUS = :STATUS";
query.Paras.Add(
"PROJECTNAME", projectName);
query.Paras.Add(
"STATUS", WorkflowStatus.Running);
return query.Select<WfProjectInstance>();

這個是個向左查詢的例子,是我的工作流框架裡面常用的查詢。

1. 我要查詢一個物件叫做WfProjectInstance

2. 這個物件的projectName = projectName、狀態=WorkflowStatus.Running

混合查詢

<!--

Code highlighting produced by Actipro CodeHighlighter (freeware)
http://www.CodeHighlighter.com/

--&gtUser user = OrmManager.Instance.Query.SelectByUpk<User>("rebornzhang@gmail.com");

IOrmAdvanceQuery
<PageRole> advance = OrmManager.Instance.GetAdvanceQuery<PageRole>();

IToLeftQuery left 
= advance.CreateToLeftQuery();
left.Condition 
= "PageRole.RoleName= :ROLENAME";
left.Paras.Add(
"ROLENAME""MERCHANT_LEVEL_03");

IToRightQuery right 
= advance.CreateToRightQuery();
right.Obj 
= user;
right.Position 
= "USER.PAGEROLELIST";

List
<PageRole> list = advance.Select(right, left);

 

最後一個是我最精華的查詢:混合查詢;結合了向右查詢和向左查詢。

具體解釋我就不說了,由於混合查詢的sql效能比較低,我用的還是比較少的。其實設計合理,一般是不用混合查詢的。

 

設計思路

現在簡單介紹一下我的ORM的一些技術思路。

1. AOP

用了.net提供的AOP思路,本質就是一個基於Message模型的呼叫。因此對實體類所有操作,會被AOP攔截,然後判斷使用者需要操作的物件、返回型別;然後轉化為SQL獲取資料。

2. Reflect

用了反射,這個也是必然的,除了對值型別(Valuetype)反射,還有自定義的class的反射,獲取後設資料,然後組成sql

3. ORM的理論

比如 User {List list;}

這個類,會被對映為三張表

A:TB_USER表

B:TB_USER_LIST的連結表

C:TB_ROLE 表

其實掌握了基本的ORM理論,知道物件如何對映為表之後,就能夠實現大部分功能了。這個還多虧了Oracle的ORm資料,寫的非常詳細,讓我少走了很多彎路。

4. 一些自定義的表名、主鍵值生成

要使用方便,那麼就要把很多靈活的操作變得不靈活,比如表名的命名、主鍵的生成,這些我都會讓ORM自己完成,不需要程式設計師手動設定。

是犧牲了一些代價,但是隻要你使用了我的orm,換回來的是非常良好的操作和維護。

5. OO的設計模式和理論

良好的設計模式事半功倍,在我的ORM框架裡面

1)所有自定義物件會被對映為一個ObjProxy物件,這個稱為物件代理;因此對自定義類的操作,會變成ObjProxy的操作

2)結合一些設計模式,能夠使快取操作、事務操作變得非常簡單,只需要做幾個切換,用一些介面的方法之類的。

總而言之,良好的設計模式是必須的。

原文地址:http://www.cnblogs.com/zc22/archive/2009/10/26/1590166.html

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-617532/,如需轉載,請註明出處,否則將追究法律責任。

相關文章