常見的是:資料庫結構=》映射object(實體屬性)=》基于實體類的操作。
還有一種:資料庫結構=》映射object(記憶體表結構)=》基于記憶體表的操作。
當然,如果你有創意,你還能創造出更多的映射載體來實作orm。
由于思維定式,很多開發者,隻有見到基于實體類映射,才會認為是一種orm架構,于是很少人去思考其它映射載體來實作orm。
這個思維定式,和早期在asp.net mvc沒出來之前,把webform架構當成asp.net一樣,于是很少人會去創造另一種開發架構。
不過要避免思維定式,有時候的确不是件容易的事~~~這需要太多知識的沉澱和積累,這個就先不扯了,下面來正題。
一般的資料庫下,都是基于sql語句解析執行的,是以orm最終都避不開生成sql再交還ado.net去執行,進而傳回結果。
由于orm存在映射關系,最簡單的是(字段名稱+資料類型)的實體映射,是以,通常隻要周遊實體的屬性就可以拿到所有字段名稱,進而組合sql去執行了。
而反射的應用,對于實體型映射的orm無疑是佳方案,節省大量代碼;通過反射,在處理時動态獲得指定對象的類型、字段名稱、字段類型、或者特性描述等資訊,進而構造出sql語句。
如果是基于記憶體表(mdatatable)映射的,則無需反射,因為映射的時候,相關結構已提前預約好了,直接周遊擷取即可。
這裡先不說基于記憶體表的映射,說說基于實體映射的設計方案:

public class users : cyq.data.orm.ormbase
{
public users()
{
base.setinit(this);
}
public int id { get; set; }
public string username { get; set; }
public datetime createtime { get; set; }
}

這種方式,增删改查,都由基類處理了,而基類一般需要三個參數:
1:子類的對象,用于反射類型及屬性的需要。
2:表名(可選,如果不寫,則從反射中拿到類名當表名)
3:資料庫連結(可選,如果不寫,則會預設約定一個配置名稱的資料庫連結)
最終的操作方式類似:

using (users u = new users())
{
u.username = "u1";
u.update(1);
}

如果按正常,我們可能會循環所有字段,全部更新;很明顯在這裡我們隻需要更新username。
于是,在設計上,我們需要額外多出一個集合,來存儲字段對應的狀态,這個集合怎麼設計,這個大夥自行發揮了。
這裡的難點,在于,如何設計擷取狀态改變上。
直接切入實體的set屬性,如:

public string username
get;
set
base.setstate(value);
}

然後事情就交給基類的setstate方法去修正對應實體的狀态,周遊屬性的時候,再比較狀态,取得隻需要更新的字段去組合即可。
這種方案,優點是:可以保持實體類的相對簡潔,通過在基類利用aop攔截子類的set方法,進而動态的調用setstate方法。
缺點是:實作有點難度,另外是由于aop基類contextboundobject的限制, 内部無法使用泛型。
即你不能實作:select<t>()類似的方法,是以最終的表達式可能需要借第三個類的tolist()方法來傳回,代碼類似:
using(users u = new users())
{
list<users> list= u.select().tolist();
}
具體的方案實作可以見我以前寫的這兩篇文章:
<a href="http://www.cnblogs.com/cyq1162/archive/2012/05/30/2526573.html">c# aop簡單掃盲及orm實體類屬性攔截示例</a>
<a href="http://www.cnblogs.com/cyq1162/archive/2012/08/29/2662492.html">aop realproxy 千年遇bug</a>

public class users
}

這種方式,實體就類似資料載體,本身不具備增删改查功能,類似把基類獨立開來操作。
最終的調用方式可能類似:

users user= dbfast.find<users>(1);//查詢記錄。
users u=new users();
u.username="u1";
dbfast.update<users>(u,1);//更新。

對于貧血模式,也有兩種對應的設計方案:

}

由于沒有基類,是以狀态的變化,無法很好的內建的,是以,這種情況的設計,通常需要多一行額外的代碼來傳遞資訊。
例如:

dbfast.setstate<users>("username",state.forupdate);//類似的多了一行來指定需要更新的一個或多個列的狀态。
dbfast.update<users>(u,1);//更新。


public int? id { get; set; }
public datetime? createtime { get; set; }

對于這種模式,可以讓值類型的預設值也為null,是以可以通過減免值為null的列,來實作更新值不為null的值。
不過對于這種方式,由于dbnull.value隻能給引用類型指派,是以值類型的字段無法重置為null。
是以,如果要實作對值類型賦null值,可能需要增加一行代碼來對指定的行指定狀态,配合着使用;或者直接操作sql語句。
記得前些日子和騰訊的架構師面試的時候,好像也交流到了這個指定列的更新的話題上,不過那時候的話題,上升到分布式話題了:
問題:大體是有一份資料載體情況下,使用者更新了某些字段,如何隻更新某些字段的話題:
1:先是說前端的過濾與傳遞隻需要更新的資料(對方:這個先假設沒有做)。
2:服務端可以做緩存,然後比較(對方:假設伺服器有很多,做了負載,如何保證)。
3:全局共享緩存或用分布式緩存(對方:假設沒有分布式緩存,隻有web伺服器緩存,隻有一份副本)
4:通過某種算法,讓使用者的請求的資料對應到相對的副本的伺服器。(對方:算法怎麼實作)
5:。。。此處省略600字了。。。
不知不覺又寫了好幾個小時了,今天就介紹到這裡了~~~謝謝大夥~~~~
最後給貼一下今天各大群熱傳的勵志文:月領1萬2小it職員五年在北京買500萬房子~~