日期:2008-06-03 浏览次数:20615 次
ICriteria是使用Expression进行数据加载的接口, 提供了设置表达式(Expression), 排序方式(Order), 分页记录等操作.
下面以一个查询Username为billy, Password为test的用户为例来分析nh中Criteria数据加载是怎样工作的.
查询代码如下:
Expression ex = Expression.And( Expression.Eq("Username", "billy"),
Expression.Eq("Password", "test") );
IList users = session.CreateCriteria( typeof(Username) ).Add( ex ).List();
这里先建立了一个Expression, 然后加入到ICriteria中. ICriteria通过session.CreateCriteria( type )获得.
注意: ICriteria的实现类CriteriaImpl是一个Internal类, 因此不能在nh程序集外直接创建.
SqlString和SqlStringBuilder对象
因后面的代码多次用到SqlString和SqlStringBuilder对象,这里先说明一下。
SqlString对象用于存储伪Sql语句中的各个部分,注意,是伪Sql语句哦~, 不是实际的sql语句,不过实际的sql语句是通过SqlString对象解析而来的。
假如我有这样的一个伪sql语句,
select * from User u
where u.Username = @Username and u.Password = @Password
那么由此产生的SqlString将包含一个这样的数组,{"select", "*", "from", "User", "where", "Username", "=", param, "and", "Password", "=", param2 }, 其中param, param2是nh中的Paramenter(参数)对象.
SqlStringBuilder对象专门用于创建SqlString对象,因为SqlString是不能修改它内部的sqlPart的,如要修改sqlPart, 必须使用SqlStringBuilder.
Expression对象
Expression是所有表达式对象的祖先, 它使用Factory Method(工厂模式)来创建具体的表达式(如相等表达式EqExpression).
这里介绍几个最要的表达式对象:
SimpleExpression: 简单表达式对象, 是所有简单操作表达式的父类, 如EqExpression, GtExpression等;
LogicalExpression: 逻辑表达式对象, 用于指定两个表达式的逻辑关系, 有AndExpression和OrExpression两个子类;
最值的关注就是Expression如何产生它的sqlString了, 这个由ToSqlString方法完成.
// *** SimpleExpression.cs 60行***
public override SqlString ToSqlString(ISessionFactoryImplementor factory,
System.Type persistentClass, string alias) {
SqlStringBuilder sqlBuilder = new SqlStringBuilder();
IType propertyType = ((IQueryable)factory.GetPersister(persistentClass)).GetPropertyType(propertyName);
string[] columnNames = GetColumns(factory, persistentClass, propertyName, alias);
string[] paramColumnNames = GetColumns(factory, persistentClass, propertyName , null);
Parameter[] parameters = Parameter.GenerateParameters(factory, alias, paramColumnNames, propertyType);
for(int i = 0; i < columnNames.Length; i++) {
if(i > 0) sqlBuilder.Add(" AND ");
sqlBuilder.Add(columnNames[i])
.Add(Op)
.Add(parameters[i]);
}
return sqlBuilder.ToSqlString();
}
取得属性对应的数据列名, 并创建Parameter对象, 在解析SqlString时将根据Parameter产生实际的IDbParameter对象.
// *** SimpleExpression.cs 65行***
public override SqlString ToSqlString(ISessionFactoryImplementor factory,
System.Type persistentClass, string alias) {
SqlStringBuilder sqlBuilder = new SqlStringBuilder();
SqlString lhSqlString = lhs.ToSqlString(factory, persistentClass, alias);
SqlString rhSqlString = rhs.ToSqlString(factory, persistentClass, alias);
sqlBuilder.Add(new SqlString[] {lhSqlString, rhSqlString},
"(", Op, ")");
return sqlBuilder.ToSqlString();
}
先得到逻辑操作两边的表达式SqlString, 然后连同逻辑操作一起加入到sqlBuilder对象中。
另外一个要关注的就是GetTypedValues方法了,它返回表达式中属性的类型和值,用于给参数赋值。
加载过程源码分析