您的位置:首页 > Web前端

NewLife.Xcode 上手指南(三) 扩展属性的使用

2012-07-31 09:06 806 查看
一、什么是扩展属性

很多ORM框架都支持类似这样的操作.以第一节的表为例,





象这样的Subject对象中有TeacherID的一般都是这样用

Subject subject = Subject.FindByID(1);
string TeacherName = subject.Teacher.Name;






这样子的话,直接就关联到Teacher对象,而不是在操作TeacherID,这是怎么做的呢? XCode会帮我们自动完成吗?

首先我们肯定XCode是会帮我们自动来做这些扩展属性的.不信,大家可以看一下Teacher对象的Teacher.Biz.cs,里面已经有了这样的一段代码




XCode是如何帮我们绑定这些属性的呢?

1.根据约定胜于配置,与其我们配置来配置去,让很多人无从上手,不如约定规则,这样更方便大家使用.于是XCode代码生成器中的帮助里有这么几条规则





nvarchar 和 varchar 的区别是存储方式不同
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个文件,覆盖之









继续我们的添加数据的操作,在subject里加点料.





在这里,我们加了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论坛地址:

http://www.newlifex.com/

大石头博客:

http://www.cnblogs.com/nnhy/

NewLife.XCode开发资源目录

/article/4749087.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: