在动手写这篇 Post 之前我得先声明一下,本人对 Castle 的了解还不够深入,仅仅在近期在项目中使用过而已,所以我的做法不一定是正确的,也不一定能给大家带来帮助,说不定还会给你带来更多的麻烦
。
把 Posts 发到首页上也是希望大家都能说出自己的想法,还有我的处理方式的可行性做一些分析和批评。
从对 Castle 一无所知到有所了解,Terrylee 的
Castle 开发系列(推荐) 给了我很大的帮助,特在此对 Terrylee 表示感谢。
对于我自己而言我并不太喜欢 Castle 封装 NHibernate 的方式, 虽然减少了配置映射文件的复杂性和易出错,但我还是更喜欢把映射文件和实体类分开来,我觉得这更加直观,看起来也不会太凌乱,唯一的缺点就是有时候会顾此失彼,但我认为这是值得的。就好比是 ASP.NET 将界面和代码相分离,但萝卜青菜各有所爱,我们所要做的就是像找女朋友一样选自己喜欢的。
Castle 把 ActiveRecordBase 声明为 abstract 以至于在实体类直接继承并实现一些自操作行为,如 Save()、 Create()、Update()、Delete() 也是我深恶痛绝日,我非常不喜欢把业务操作移殖到实体层去,层与层之间的职任应该划分得很清晰,要不然我看了就觉得不舒服,可能有人会说如果不喜欢我完全可以不去理会它,当它不存在就是了,但它却确确实实地存在着,还是 public ,无论走到那里都能看到自己不喜欢的东西我还能无动于衷吗?而且我们还有同样方便方法来代替,稍后将会讲到,所以我要把 ActiveRecordBase 改造成为 ActiveRecord 并且只留下静态方法,相当于一个 NHibernateHelper。
至于 IOC 容器我更喜欢 Spring.Net,虽然比较复杂,但还是那句话,萝卜青菜各有所爱。
接下来就开始我们的改造工作,首先是 Session 管理的问题,由于现在我没时间研究 Castle 的源码,加上水平有限,决定另寻它路。于是在
DDLLY命名空间 里找到了
NHibernate的Session管理,我承认通过 IHttpModule 来存储 Session 不失为了一个好方法,但它仅解决了客户端请求操作的问题,当请求来自服务器端的时候 HttpContext.Current 将为 NULL 值。我的解决方法是新建一个 SessionObject 类,类中两个属性,一个用于存储 Session 值,另一个用于标记操作完成后是否关闭 Session,当 HttpContext 为空时创建一个新的 SessionObject 实例并将其标记为需要 Close,这样做的缺点是每次操作都必须检查是否需要关闭 Session,但暂时还想不到更好的解决方法就先凑合着使用了。
下面是我改造过后的代码,这个类并不能独立工作,它还依赖于其它类,在后面我会放上完整项目供下载。
<!---->namespace Yyw.DBUtility.NH.ActiveRecords
{
using System;
using System.Collections;
using System.Collections.Generic;
using NHibernate;
using NHibernate.Expression;
using Yyw.DBUtility.NHibernateSessionStorage;
/**//// <summary>
/// Base class for all ActiveRecord classes. Implements
/// all the functionality to simplify the code on the
/// subclasses.
/// </summary>
[Serializable]
public class ActiveRecord
{
/**//// <summary>
/// Constructs an ActiveRecordBase subclass.
/// </summary>
public ActiveRecord()
{
}
static methods#region static methods
/**//// <summary>
/// Invokes the specified delegate passing a valid
/// NHibernate session. Used for custom NHibernate queries.
/// </summary>
/// <param name="targetType">The target ActiveRecordType</param>
/// <param name="call">The delegate instance</param>
/// <param name="instance">The ActiveRecord instance</param>
/// <returns>Whatever is returned by the delegate invocation</returns>
//public static object Execute(Type targetType, NHibernateDelegate call, object instance)
//{
// if (targetType == null) throw new ArgumentNullException("targetType", "Target type must be informed");
// if (call == null) throw new ArgumentNullException("call", "Delegate must be passed");
// EnsureInitialized(targetType);
// ISession session = _holder.CreateSession( targetType );
// try
// {
// return call(session, instance);
// }
// catch(Exception ex)
// {
// throw new ActiveRecordException("Error performing Execute for " + targetType.Name, ex);
// }
// finally
// {
// _holder.ReleaseSession(session);
// }
//}
/**//// <summary>
/// Finds an object instance by a unique ID
/// </summary>
/// <param name="targetType">The AR subclass type</param>
/// <param name="id">ID value</param>
/// <param name="throwOnNotFound"><c>true</c> if you want to catch an exception
/// if the object is not found</param>
/// <returns></returns>
/// <exception cref="ObjectNotFoundException">if <c>throwOnNotFound</c> is set to
/// <c>true</c> and the row is not found</exception>
public static T FindByPrimaryKey<T>(object id, bool throwOnNotFound) where T : class
{
SessionObject sessionObj = NHibernateDatabaseFactory.CreateSession();
ISession session = sessionObj.Session;
try
{
return session.Load<T>( id );
}
catch(ObjectNotFoundException ex)
{
if (throwOnNotFound)
{
String message = String.Format("Could not find {0} with id {1}", typeof(T).Name, id);
throw new NotFoundException(message, ex);
}
return default(T);
}
catch(Exception ex)
{
throw new ActiveRecordException("Could not perform Load (Find by id) for " + typeof(T).Name, ex);
}
finally
{
if (sessionObj.IsNeedClose)
session.Close();
}
}
/**//// <summary>
/// Finds an object instance by a unique ID
/// </summary>
/// <param name="targetType">The AR subclass type</param>
/// <param name="id">ID value</param>
/// <returns></returns>
public static T FindByPrimaryKey<T>(object id) where T : class
{
return FindByPrimaryKey<T>(id, true);
}
/**//// <summary>
/// Returns all instances found for the specified type.
/// </summary>
/// <param name="targetType"></param>
/// <returns></returns>
public static IList<T> FindAll<T>() where T : class
{
return FindAll<T>((Order[]) null);
}
/**//// <summary>
/// Returns a portion of the query results (sliced)
/// </summary>
public static IList<T> SlicedFindAll<T>(int firstResult, int maxresults, Order[] orders, params ICriterion[] criterias) where T : class
{
SessionObject sessionObj = NHibernateDatabaseFactory.CreateSession();
ISession session = sessionObj.Session;
try
{
ICriteria criteria = session.CreateCriteria(typeof(T));
foreach( ICriterion cond in criterias )
{
criteria.Add( cond );
}
分享到:
相关推荐
Castle.ActiveRecord官方已经停止更新了,官方最高支持到NHibernate 3.1.0.4000,这个版本还有不少问题(例如:[NH-2213] - CLONE -Wrong parameters order in IQuery with SetParameterList and Filter)。...
Castle.ActiveRecord 3.0.0+NHibernate 3.0.0.4000+SQLite+NVelocity 服务器控件 组合案例 VS环境:VS2010 数据访问框架: Castle.ActiveRecord 3.0.0 + NHibernate3.0.0.4000 当前测试数据库:SQLite (要改变数据库...
castle ActiveRecord 源代码 nhibernate封装 C#
CASTLE ACTIVERECORD学习实践(1):快速入门指南 CASTLE ACTIVERECORD学习实践(2):构建配置信息 CASTLE ACTIVERECORD学习实践(3):映射基础 CASTLE ACTIVERECORD学习实践(4):实现ONE-MANY关系的映射 CASTLE...
将ActiveRecord中的NHibernate升级到3.3.0GA,排除编译的bug问题,保留ActiveRecord的完整功能,【Castle.ActiveRecord 升级NHibernate到3.4.0GA】的功能不完整!
Castle.ActiveRecord 3.0.0+NHibernate 3.0.0.4000+SQLite+NVelocity 服务器控件 组合案例 VS环境:VS2010 数据访问框架: Castle.ActiveRecord 3.0.0 + NHibernate3.0.0.4000 当前测试数据库:SQLite (要改变...
包含ActiveRecord、Castle API、NHibernate.Documentation、NHibernate.Reference 等关于Castle ActiveRecord的帮助文档
Castle ActiveRecord快速入门指南,ActiveRecord帮助文档
ActiveRecord最终版,由于ActiveRecord引用了ISet集合,Iesi.Collections.3.4.1.4000以后已经把ISet去掉了,所以ActiveRecord引用的NHibernate的版本的更新只能到3.4.1.4000此为止。 引用其他资源版本如下: ...
Castle.ActiveRecord For .NET FrameWork 2.0 如果你想使用Castle.ActiveRecord,但又不想使用.NET Framework 3.0/3.5/4.0或更高版本,那么这个就是你所需要的,For .NET FrameWork 2.0,我整理了好久,自己从官方...
Castle ActiveRecord CHM帮助文档 最全的学习资料,经典例子,入门必备,技术人员随身携带的备查工具书。
Castle.ActiveRecord 的资料很多,但是WINFORM的没几个,于此我专门写了个例子献给初学Castle.ActiveRecord的童鞋们,希望这篇文档能够帮到你们。这个例子使用的是ACCESS数据库,从单表,一对多,多对多,数据绑定,...
Castle ActiveRecord 2.0
ActiveRecord 手册Castle ActiveRecord学习 快速入门指南
简单Castle.ActiveRecord.Generator的例子。 包括添加,修改,删除,察看的基本功能。 包含建库脚本。
C# Castle.ActiveRecord CS源码示例教程.zip
基于Castle ActiveRecord实现数据访问层的PetShop ASP.NET源码。
Wpf使用Castle.ActiveRecord的示例,Castle针对.NET平台下的一个非常优秀的开源项目,其对数据访问层封装的非常不错,使开发者能省下大量数据访问的工作量,此示例比较基础,适合入门的朋友参考下,所需要的控件已在...
找这个资源的人都知道这是干什么的,就不多说什么了,
Apress Pro ActiveRecord Databases with Ruby and Rails <br>Active Record has primarily been covered as a subsection, or maybe as a chapter or two, within a larger scoped book generally about the ...