NHibernate入门系列: 使用Criteria载入对象

NHibernate会话提供一种使用表达式(就像SQL语句的where表达式)来载入数据的方法, 以取得满足条件的对象集合。

通过CreateCriteria方法, 可以取得一个ICriteria接口, 这个接口用于操作表达式和排序字段. 由CriteriaImpl类实现,此类加有Internal修饰,因此不能在程序集外显示创建, CreateCriteria方法需要一个要加载对象类型的参数.

这里列出ICriteria接口中的一些常用方法:

Add:加入条件表达式(Expression对象),此方法可多次调用以组合多个条件;
AddOrder:加入排序的字段(Order对象);
List:执行查询, 返回满足条件的对象集合。
SetMaxResults:设置返回的最大结果数,可用于分页;
SetFirstResult:设置首个对象返回的位置,可用于分页;
SetTimeout:设置操作的超时值,此值将传递给IDbCommand对象;

Expression(表达式)

Expression类是所有表达式类的祖先. 这是一个抽象(abstract)类, 同时也是一个类工厂(Factory Method模式), 用于创建派生的表达式对象, 用意是很明显的, 隐藏了派生类的细节,使我们可通过一致的方法来创建表达式对象.

下面列出一些Expression中常用的方法:

Eq:得到一个相等判断的表达式, 等同于 propertyName = value;
Gt:得到一个大于判断的表达式, 等同于 propertyName > value;
Like:得到一个相似判断的表达式, 等同于 propertyName like value;
And:得到两个表达式And操作后的表达式, 等同于 expression1 and expression2;
Or:重到两个表达式Or操作后的表达式, 等同于 expression1 or expression2;

更多的Expression请参考相关文档或源代码。

Order(排序)

Order类用于向ICriteria接口提供排序信息. 这个类提供了两个静态方法, 分别是Asc和Desc, 顾名思义就是创建升序和降序的Order对象.
例如要取得一个按更新日期(Updated)降序的Order对象, 使用Order.Desc("Updated")就可以了.

示例

下面以几个例子来说明使用Criteria载入对象的用法:

1. 取得用户名(Username)为billy的用户对象:


Expression ex = Expression.Eq( "Username", "billy" ); // ( Username = 'billy' )
IList users = session.CreateCriteria(typeof(User)).Add( ex ).List();

2。取得用户名(Username)为billy, 密码(Password)为123456的用户对象

Expression ex = Expression.And(
Expression.Eq("Username", "billy"),
Expression.Eq("Password", "123456")
); // ( Username='billy' and Password='123456' )
IList users = session.CreateCriteria(type(User)).Add( ex ).List();

3. 取得数据中第20-40的用户对象。

ICriteria c = session.CreateCriteria(typeof(User));
IList users = c.SetFirstResult(20).SetMaxResults(20).List();

对于SQLSERVER,数据定位采用的是IDataReader前滚至firstResult处,然后取maxResults条记录.

4. 取得按注册日期(Regdate)降序排序后的用户对象.

ICriteria c = session.CreateCriteria(typeof(User));
IList users = c.AddOrder( Order.Desc("Regdate") ).List();

使用Criteria加载数据的不足:

1. 当使用SetFirstResult和SetMaxResults限制返回的对象数时,无法得知对象的总数;
2. 当前版本不支持关联查询(hibernate好像可以);

标签: NHibernate Criteria 入门

Castle IOC容器与Spring.NET配置之比较

  我本人对于Spring.NET并不了解,本文只是通过一个简单的例子来比较一下两者配置之间的区别。在Castle IOC容器中,提出了自动装配(Auto-Wiring)的概念,即由容器自动管理组件之间的依赖关系,我们无需自己编写XML配置文件来配置组件之间的依赖关系。在Spring.NET中也是支持自动装配的,但是并不推荐使用,它贯穿着一种思想就是一切皆为XML配置,这是两者之间最大的一个区别。

  关于自动装配,来自于Spring.NET的支持者认为让容器自动管理,会让我们无法控制组件的依赖关系,如果该为XML配置,可以让我们知道自己在做什么,我们指定了哪些依赖关系,方便进行控制和管理;而来自于Castle IOC的支持者认为如果不让容器自动管理,手工配置会变得非常之复杂,配置文件也会变得非常繁冗,如果系统中的组件非常之多的时候,管理工作会变得很困难。

  我们来看一个简单的例子,有这样一个组件MyMainComponent,它依赖于MyComponent1、MyComponent2,并且它在构造函数中还需要接收一个整型的参数。
public class MyMainComponent
{
MyComponent1 _com1;
MyComponent2 _com2;
int _i;
public MyMainComponent(MyComponent1 com1,MyComponent2 com2,int i)
{
this._com1 = com1;
this._com2 = com2;
this._i = i;
}
}
public class MyComponent1
{
public MyComponent1()
{
//
    }
}
public class MyComponent2
{
public MyComponent2()
{
//
    }
}
  如果用采用Spring.NET,它采用XML进行组件之间的连接,配置文件如下,需要在配置文件中指定每一个对象及其它们之间的依赖,同时在配置文件中区分是构造函数还是其他方法:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<object id="myManComponent" class="CastleDemo.MyMainComponent, CastleDemo">
<constructor-arg>
<ref object="mycomponent1" />
</constructor-arg>
<constructor-arg>
<ref object="mycomponent2" />
</constructor-arg>
<constructor-arg>
<value>1</value>
</constructor-arg>
</object>
<object id="mycomponent1" class="CastleDemo.MyComponent1, CastleDemo" />
<object id="mycomponent2" class="CastleDemo.MyComponent2, CastleDemo" />
</configuration>
Castle IOC中同样需要配置文件,但相比之下,就简单了很多:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<components>
<component id="myMainComponent">
<parameters>
<i>1</i>
</parameters>
</component>
</components>
</configuration>
  在Castle IOC中的配置并不需要指定组件之间的关联,它会自动通过Windsor来处理;我们只是配置了一个参数i,这个i是MyMainComponent中的构造函数中不存在依赖关系的那个参数。
public class App
{
public static void Main()
{
IWindsorContainer container = new WindsorContainer(new XmlInterpreter("../../BasicUsage.xml") );
container.AddComponent( "myMainComponent",
typeof(MyMainComponent));
container.AddComponent( "myComponent1",
typeof(MyComponent1));
container.AddComponent( "myComponent2",
typeof(MyComponent2));
}
}
  这样添加组件后,
  WindsorContainer会自动调用MicroKernel中的ConstructorDependenciesModelInspector来处理组件的构造函数依赖。

  通过上面的这个简单例子比较可以看出,如果我们想要增加一个组件之间的依赖关系或者增加一个组件使用Castle要比使用Spring.NET容易很多,Spring.NET复杂的配置文件会给我们开发带来很来不可预料的错误;Castle根据对象的依赖关系,采用自动装配,不需要配置组件的依赖,另外为了符合构造注入和属性注入,Castle的配置文件并没有像Spring.Net那样区分构造函数还是其他的方法,同时直接使用Parameters,而不是使用构造函数参数之类的区分。

标签: Spring.NET Castle IOC 容器