一、什么是擴展屬性
很多ORM框架都支持類似這樣的操作.以第一節的表為例,
象這樣的Subject對象中有TeacherID的一般都是這樣用
Subject subject = Subject.FindByID(1);
string TeacherName = subject.Teacher.Name;
這樣子的話,直接就關聯到Teacher對象,而不是在操作TeacherID,這是怎么做的呢? XCode會幫我們自動完成嗎?
首先我們肯定XCode是會幫我們自動來做這些擴展屬性的.不信,大家可以看一下Teacher對象的Teacher.Biz.cs,里面已經有了這樣的一段代碼 
XCode是如何幫我們綁定這些屬性的呢?
1.根據約定勝於配置,與其我們配置來配置去,讓很多人無從上手,不如約定規則,這樣更方便大家使用.於是XCode代碼生成器中的幫助里有這么幾條規則
varchar是按字節存儲的.而帶"n"的nvarchar是按字符存儲的
比如說 varchar(40),能存儲40個字節長度的字符,存儲中文字符的時候,因為中文字符1個字符就等於2個字節.所以varchar(40)只能存儲20個中文字符.
nvarchar(40),就可以存儲40個中文字符,也就是說可以存儲80個字節長度的字符.nvarchar要相對於存儲的字符類型.比如有些字符是占3個字節的.
需要trim的是(n)char....
3.第6條XCode會自動把數據庫注釋生成為代碼注釋,如果沒有注釋XCode也會嘗試自動翻譯(這里是連接Google翻譯器? 我想XCode不會真的自己集成了個字典吧~~~)
4.想要自動生成擴展屬性,從表的字段命名規則為(主表名+主表主鍵字段) ,這里有Subject表中存在TeacherID,又有Teacher表中以ID為主鍵 所以就能關聯生成擴展屬性.
5.似乎一些擴展查詢是根據索引來的,如果你建立了以TeacherID和Subject.Name為主的索引,似乎XCode會在Subject表中生成一個這樣的查詢方法,FindAllByTeacherIDAndSubjectName(int teacherid,string subjectname);
6.最主要是請放棄那些無意義的前最tbl拉,tb拉,tab拉,tab_Student這些表名都不要用,直接用Student簡潔明了
二、XCode中如何自己寫擴展屬性
就像上面的例子中,Teacher對象中已經有了擴展屬性EntityList<Subject> Subjects; 但是Subject中似乎沒有給我們自動生成擴展屬性Teacher,這里我們就自己來寫一個把,其實很簡單
#region 擴展屬性
private Teacher _Teacher;
public Teacher Teacher
{
get
{
if (_Teacher == null && _TeacherID > 0 && !Dirtys.ContainsKey("Teacher"))
{
_Teacher = Domain.Teacher.FindByID(_TeacherID);
Dirtys["Teacher"] = true;
}
return _Teacher;
}
set { _Teacher = value; }
}
#endregion
這里解釋下代碼,為什么這么寫擴展屬性,根據樓主的理解,Dirtys是一個字典,標識這個Teacher有沒有查過,為什么要用這個標志來標識呢,
應該是基於這樣一種考慮,如果Teacher!=null那么肯定Teacher已經是查過了的,但是萬一Teacher查過數據庫了仍然是null,那么就需要一個標識來記錄,我已經查過數據庫拉,就算Teacher==null也不用再查拉,直接返回null吧,這樣來減少數據庫的查詢,提高Cache命中率.
這樣寫好之后,就可以在前台利用subject.Teacher來獲得教師的屬性拉.我們來測試下.
先給Teacher表加點數據,在這里發現個第一節的bug,Phone竟然用的是Int類型,025輸入變成25,輸入手機號超出int的范圍,這是個bug如何修復呢,首先我們修改數據庫,其次利用Xcode代碼生成器針對這個表重新生成一下.然后覆蓋項目中的2個文件,這里Teacher.My.cs就體現出優勢了,我們自己的代碼完全不怕誤操作覆蓋.
這里,我們替換修改下數據庫,
生成下代碼,同樣是實體數據和實體業務都生成一遍,然后得到2個文件,覆蓋之
在這里,我們加了3條數據,主要是測試XCode是不是如我們的猜想一樣,命中Cache不用查數據庫.
為了查看到SQL語句,請確保config里這2個開關已經打開,第二講中我復制了這些語句,但是忘記打開開關了…jiong一個
<appSettings> <!--是?否?啟?用?調獺?試?,?默?認?不?啟?用?--> <add key="XCode.Debug" value="true"/> <!--是?否?輸?出?SQL語?句?,?默?認?為aXCode調獺?試?開a關?XCode.Debug--> <add key="XCode.ShowSQL" value="true"/> <!--設Θ?置?SQL輸?出?的?單蹋?獨à目?錄?,?默?認?為a空?,?SQL輸?出?到?當獺?前°日?志?中D。£生Θ?產ú環·境3建¨議皚?輸?出?到?站?點?外猘單蹋?獨à的?SqlLog目?錄?--> <add key="XCode.SQLPath" value=""/> <!--是?否?啟?用?反ぁ?向ò工¤程ì,?默?認?不?啟?用?。£反ぁ?向ò工¤程ì可é以?實害?現?通?過y實害?體?類え?反ぁ?向ò更ü新?數簓據Y庫a結á構1--> <add key="XCode.Negative.Enable" value="true"/> </appSettings> 我不得不說,我的代碼着色器對中文支持很爛哎````
三、開始測試
直接建立一個新的頁面,叫test.aspx來做今天的測試吧~~~我已經從7點半寫到8點40了...還沒結束呢...我已經不想寫完整的例子了...拿個頁面做個簡單測試吧..
protected void Page_Load(object sender, EventArgs e) { Domain.Subject subject1 = Domain.Subject.FindByID(1); Response.Write(string.Format("第{0}個科目,科目名稱:{1},任課老師:{2},任課老師辦公室:{3},任課老師電話:{4}<br/>", subject1.ID, subject1.Name, subject1.Teacher.Name, subject1.Teacher.Office, subject1.Teacher.Phone)); Domain.Subject subject2 = Domain.Subject.FindByID(3); if(subject2.Teacher == null) { Response.Write(string.Format("第{0}個科目,科目名稱:{1},任課教師為null",subject2.ID,subject2.Name)); } }
如果沒有配置SQLPath的話,可以直接在項目根目錄下,有個log文件夾,然后以日期命名的txt就是SQL日志.可以進去查看到系統運行時下的SQL
最后我發現...我的猜想都錯了....XCode初始化了所有的實體,然后全部從Cache命中.....初始化完了之后一次SQL都沒下....
然后又發現,隔一段時間就會有2句Select * from teacher和subject ,估計應該是XCode的Cache更新時間到了,所以自動更新下最新的緩存.
XCode內部的實現我就不糾結了,基本猜測方向沒錯,具體怎么實現的,各位看官自行閱讀XCode的源碼吧.XCode是開源的哦...
本節就到這里,下一節我們介紹XCode的級聯刪除和更新. 下期再見~
本節Demo
http://dl.dbank.com/c0wyn9igvt
XCode上手指南系列:
NewLife.XCode 上手指南
NewLife.XCode 上手指南(二) 反向工程使用舉例
NewLife論壇地址:
大石頭博客:
NewLife.XCode開發資源目錄
http://www.cnblogs.com/asxinyu/archive/2012/06/02/2532210.html











