词条统计
浏览次数:5374 次
编辑次数:11次 历史版本
最近更新:2013/8/11
创建者:掷鸡蛋者

本文原是论坛帖子,讨论见此处:http://www.wojilu.com/Forum1/Topic/152 


下面就可能被关心的问题逐一说明。本文会经常更新,不断补充。


0、我记录ORM有什么优点?

1)同时支持多种数据库;
2)速度快:内置透明缓存机制,只要内存足够,大多数时候,速度超过原生的sql查询;
3)使用简单;
4)面向对象的思维模式;
5)另外还有:简单方便的sql直接运行机制。


1、是不是目前只能使用 Int 类型的主键,无法使用 GUID 主键?
[答] 是的。而且你在领域模型中不用另外定义 Id ,因为你继承的基类 ObjectBase 已经自带了 Id。虽然 GUID 在数据迁移等场合更加方便,但这个框架更多的考虑到 url 等的友好性,所以暂不支持。争取将来支持。如果实在要使用,可以参看此处的做法:http://www.wojilu.com/tag/guid 

2、虽然框架可以根据领域模型自动建表,但如果修改了模型,还可以同步到数据表中吗?
[答] 很遗憾,目前不可以,还没有找到非常完善又简单的解决方案。你需要手动打开数据表更新字段信息。

3、这个 ORM 支持多个数据库吗?
[答] 支持。而且配置很简单。先看一下配置的截图:



4、这个 ORM 支持哪几种数据库?
[答] 目前支持sqlserver/access/mysql,将来会支持更多数据库。

如何使用sqlserver数据库?参看:http://www.wojilu.com/Forum1/Topic/67 
如何使用mysql数据库?参看:http://www.wojilu.com/common/page/77 

可以使用sqlserver express吗?可以。参看:http://www.wojilu.com/Forum1/Post/2109 

5、支持存储过程吗?
[答] 不支持。这是ORM的特点,或者说,ORM的目的就是丢弃存储过程。这个思路可能需要慢慢接受。主要原因,在于如果使用存储过程,往往意味着把业务逻辑浓缩进存储过程中;这和以领域模型为中心的思路有悖。

更多说明参看:http://www.wojilu.com/Forum1/Topic/358 


6、能就常用的查询用法举些例子吗?

[答]例子如下(注意,下面例子中的select方法不建议使用,因为对缓存不利):

根据Id查询
TMember member = TMember.findById( 8 );

参数化查询1
List<Article> articles = TArticle.find( "Title=:t" ).set( "t", art.Title ).list();

参数化查询2
List<TCat> cats = TCat.find( "Id>:myid" ).set( "myid", 5 ).select( "Id,Name,ArticleCount" ).list();

参数化查询3(id in 的特殊处理)

List<TCat> cats = TCat.find( "Id in (:id1,:id2,:id3)" )

                .set( "id1", 6 )

                .set( "id2", 7 )

                .set( "id8", 8 )

                .list();——这句是对的。或者拼接ids,不使用参数化

注意,不应该是List<TCat> cats = TCat.find( "Id in (:ids)" )

                .set( "ids", "6,7,8" )

                .list();——这句是错误的

更多说明在这里:http://www.wojilu.com/Forum1/Topic/1108


参数化查询4(like语句中的特殊处理)

正确的做法是:Post.find("Status=0 and Title like '%'+:t+'%'").set("t",t).list()

注意:不是 Post.find("Status=0 and Title like '%:t%'").set("t",t).list()——这是错误做法,注意区分。


根据属性查询1(不需要联表查询)
List<TArticle> articles = TArticle.find( "Member.Id=7" )
.
select( "Id,Title,Member.Id,Cat.Name,Cat.ArticleCount,Board.Name" )
.
list();// ——警告:不推荐使用select方法。使用了select,虽然可以减少字段传输,但无法利用缓存;有时候还会和缓存冲突。如果你没有耐心调试,请勿使用。


根据属性查询2
List<TArticle> articles = TArticle.find( "Member.Id=:mid" )
.
set( "mid", 7 )
.
select( "Id,Title,Member.Id,Cat.Name,Cat.ArticleCount,Board.Name" )
.
list(); 


根据属性查询3(需要联表查询)
List<TArticle> articles = TArticle.find( "Member.Id=:mid and Cat.Name=:catname order by Id desc, Member.Id asc" )
.
set( "mid", 7 )
.
set( "catname", "音像世界" )
.
list();


查询全部
List<TCat> results = TCat.findAll();

查询全部(等效于findAll)
List<TArticle> articles = TArticle.find( "" ).list();

翻页
DataPage<Article> plist = Article.findPage( "IsDelete=0" );

int rd = plist.RecordCount; // 返回的结果数量
int pageCount = plist.
PageCount; // 共有几页
string pagerBar = plist.
PageBar; // html形式的翻页区,包括翻页链接
List<Article> 
list = plist.Results; // 结果集


翻页(参数带每页记录数)
DataPage<Article> plist = Article.findPage( "IsDelete=0", 25 ); //每页25条记录


直接使用 sql 查询
List<Article> list = Article.findBySql( "select * from Article" );

统计1
int count = TCat.count();

统计2
count = TCat.count( "Id=3" );

统计3
count = TArticle.count( "Member.Id=7" );

统计4
count = TArticle.count( "Author='周做人' " );

统计5(速度稍慢,但可以使用参数)
count = TArticle.find( "Member.Id=:mid" ).set( "mid", 7 ).count();

更新(全部属性更新)
Article article = Article.findById( 2 );
article.Title = "my new title";
article.update(); 


单独更新某个属性
Article article = Article.findById( 2 );
article.Title = "my new title";
article.update( "Title" ); 


批量更新
Article.updateBatch( "set IsDelete=1", "CategoryId=2" );

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


批量删除
Article.deleteBatch( "CategoryId=2" );


排序
http://www.wojilu.com/Forum1/Topic/324


7、某些复杂的联表查询是不是不能使用?如何直接运行sql?
[答]是的。ORM虽然有点很多,但不是全能的。有些复杂的联表、统计查询,建议你直接使用sql语句。
其实,使用我记录ORM执行sql,是非常简单、高效的。
教程参看:http://www.wojilu.com/common/page/166


8、如何防止sql注入?

a)推荐使用参数化查询方式,比如 find( "" ).set( "", "" ).list() 这个是防sql注入的

b)其他如果要拼接字符串的话,需要自己过滤布安全字符。你也可以使用框架自带的一个简单的 strUtil.SqlClean 方法

c)大量的查询使用 ctx.PostInt 等获取强类型数据,能增强可靠性


9、多对多映射如何实现?对象继承如何实现?
关于“多对多”等关联操作:http://www.wojilu.com/forum1/topic/2105 
关于继承:http://www.wojilu.com/Forum1/Topic/159


10、日期比较如何实现?

参看:http://www.wojilu.com/Forum1/Topic/360 


11、如何获得插入之后的ID?
参看:http://www.wojilu.com/Forum1/Topic/327 


12、如何理解ORM中的一级缓存和二级缓存(透明缓存)?
参看:http://www.wojilu.com/forum1/topic/4246 
和:http://www.wojilu.com/Forum1/Post/2165 


13、如何将对象的属性映射到数据库字段?如果属性名称和字段名称不一致的话。

 [Table("你的表名称")]
public class Article {

    [Column(Name="你的列名称")]
    public String Name {get;set;}

}

如上图蓝色部分,加上 Column 批注,可以映射字段,加上 Table 批注,可以映射表名称。


14、如何给所有的数据表加上前缀?

打开 /framework/config/orm.config,填写TablePrefix(下图红字部分),然后重启网站或程序。 

{
    ConnectionStringTable:{......},

    AssemblyList:["......"],

    TablePrefix:"此处填写table前缀",
    ApplicationCache:true,
    ......其他配置

}

注意行末的逗号。如果还有下一行,请加上逗号。