wojilu系统的ORM介绍

wojilu系统是一个包含了很多很多子系统的框架,当然,ORM也是其中一个很有用的系统。

wojilu ORM 尽量设计得简单易用,从下图可以看出,总共也就9个方法(重载方法不算)。

下面举一些例子来演示:

findById

Article article = Article.findById( 2 );

findAll

List<Article> list = Article.findAll();

find

说明:本方法最强大,一般的查询、搜索都使用本方法。

List<Article> list = Article.find( "Title=:t and IsDelete=:isdel" )
    .set( "t", "" )
    .set( "isdel", 1 )
    .list();

List<Article> list = Article.find( "Title=:t and IsDelete=:isdel" )
    .set( "t", "" )
    .set( "isdel", 1 )
    .first(); 

参数化查询说明1(id in 的特殊处理)
List<TCat> cats = db.find<TCat>( "Id in (:id1,:id2,:id3)" )
                .set( "id1", 6 )
                .set( "id2", 7 )
                .set( "id8", 8 )
                .list();——这句是对的。或者拼接ids,不使用参数化
注意,不应该是List<TCat> cats = db.find<TCat>( "Id in (:ids)" )
                .set( "ids", "6,7,8" )
                .list();——这句是错误的

参数化查询说明2(like语句中的特殊处理)
正确的做法是:Package.find("Status=0 and Title like '%'+:t+'%'").set("t",t).list()
注意:不是 Package.find("Status=0 and Title like '%:t%'").set("t",t).list()——这是错误做法,注意区分。

 

findPage

DataPage<Article> plist = Article.findPage( "IsDelete=0" );
int rd = plist.RecordCount;
int pageCount = plist.PageCount;
string pagerBar = plist.PageBar;
List<Article> list = plist.Results;

findBySql

List<Article> list = Article.findBySql( "select * from Article" );

count

int articleCount = Article.count( "IsDelete=0" );

insert

Article article = new Article();
...
article.insert();

update

Article article = Article.findById( 2 );
article.Title = "my new title";
article.update(); 

update( string property )

Article article = Article.findById( 2 );
article.Title = "my new title";
article.update( "Title" );  

updateBatch

Article.updateBatch( "set IsDelete=1", "CategoryId=2" );

delete

Article article = Article.findById( 2 );
article.delete();  

deleteBatch

Article.deleteBatch( "CategoryId=2" );

以上方法看似简单,实际上可以对付99%的数据操作需求,尤其是第三个find方法,采用参数化查询方式,可以做大多数事情。

另外的 1% 的需求,您可以通过 db.run 对象操作,也就是直接使用原生的sql语句。

在设计 wojilu ORM 的时候,改版了好多次,曾经的接口方法要多很多,也复杂很多。比如曾经有一个 findBy( string property, object val ) 方法,看似很有用,在实际项目中进行统计之后,才发现用到的地方极少,就砍掉了,万一需要,您也可以通过find方法实现。

这就是 wojilu ORM 的设计原则:简洁!简洁!简洁!实用!实用!实用!

wojilu ORM 配置:

同时,wojilu的ORM,如果和wojilu的缓存系统一起使用,则可以将数据库访问的性能达到一个极致。

 

wojilu ORM中的缓存分成两部分:ContextCache(一级缓存)和ApplicationCache(二级缓存)。

ContextCache(一级缓存)这里的ContextCache仅仅存在于一个上下文中,具体到网站访问上,就是页面开始到页面结束,之后就不存在了。虽然缓存时间是瞬间的(比如只有几十毫秒),但也很有意义。它不是静态缓存,作为一级缓存,在web情况下,它是放在HttpContext中的。它的特点是随用随弃,不用考虑缓存策略,不会给内存增加负担,而在实战中很有价值,比如一个很大的页面分成了5个部分,在每个部分进行数据绑定的时候,可能出现重复的数据读取,比如页面头部查询了user,页面中部、数据列表等也查询了user,这些重复的查询都会默认直接从ContextCache中读取。如果是自己手写sql,往往就要细心避免这里的sql重复查询问题。

ApplicationCache(二级缓存)能长时间存在于内存中,作为二级缓存,往往是为了应付性能方面的压力。

ContextCache基本上是必须的、默认的,而ApplicationCache则需要根据实际的应用场景来实施。通常情况下,只有从一级缓存中检索不到数据,才去二级缓存中继续检索,如果二级缓存中也没有,才去数据库读取。

一级缓存是默认自动开启的,你不需要管他。

二级缓存需要手动打开。对于一个网站来说,最容易看出优化效果的,是二级缓存。它的主要目的就是实现透明缓存,所谓“透明缓存”,也就是不需要手工控制缓存的失效或过期,由ORM自动管理。
实现“透明缓存”的关键之处在于,在启用了ApplicationCache之后,每次查询出数据并加入缓存的时候,同时也缓存一个加入时间的时间戳

我们以 ApplicationPool(对象缓存池) 为例,当将一个对象加入缓存的时候——
        public void Add( IEntity obj ) {

            if (obj == null) return;

            String key = CacheKey.getObject( obj.GetType(), obj.Id );
            addToApplication( key, obj );
            CacheTime.updateObject( obj ); // 加入缓存的时候,设置最新 timestamp
        }

除了将对象放入缓存 addToApplication ,还保存了一个时间戳 CacheTime.updateObject( obj ) 。有了这个时间戳,那么,ORM就会知道哪些对象是更新过的,哪些对象是没有更新过的。在对象更新或删除的时候,会让缓存的对象刷新时间戳,比如在 UpdateOperation 中——
CacheTime.updateTable( entityInfo.Type );
表明这个对象已经被更新过了,所以下次客户端再检索就不会从缓存中取过期的对象。

对于一系列对象的列表,会在缓存中维护一个对象的id的列表,而不是直接将List<Object>放进去,请看 ApplicationPool 的 addList 方法,
            List<int> ids = new List<int>();
            foreach (IEntity obj in objList) ids.Add( obj.Id );
            addToApplication( key, ids );

缓存中存放的是 ids。

总结一下:二级缓存的好处有两个:一是大幅度提高性能,降低数据库压力,不用重复查询数据库;二是全自动管理缓存,避免手工管理缓存的复杂度和bug。


关于ORM中启用数据库事务的介绍:  http://www.cnblogs.com/TextEditor/archive/2011/06/25/2090401.html

posted @ 2011-06-26 21:51  灰毛毛  阅读(2275)  评论(5编辑  收藏  举报