在投影上使用NHibernate拦截器

本文关键字:NHibernate 投影 | 更新日期: 2023-09-27 17:53:34

我有这样的情况:

我使用Nhibernate来映射一个实体'User',它映射在Sql中的一个大表上,出于性能原因,我创建了一个轻量级实体'LightweightUser',它只有一小组属性,并且是NOT映射在hbm文件或其他什么,我使用Nhibernate投影技术来连接'LightweightUser'实体。这两个实体都是从一个包含Id属性的简单类"Entity"派生出来的。

以上实现工作良好,sql查询更小==更快。

但是在我的Nhibernate SessionFactory中,我还注入了一个Nhibernate拦截器。拦截器的OnLoad方法在我从NHibernate Dao获得'User'实体时被调用,但是当我从NHibernate Dao获得'LightweightUser'实体时,拦截器未触发 (OnLoad方法)。

这可能与NHibernate SessionFactory不知道我的'LightweightUser'实体有关。是否有一种方法来通知会话工厂/拦截我的"轻量级"实体的存在?还是有其他的技术可以把投射连接到拦截器上?是的,我也可以复制'hbm'文件为我的轻量级实体,但这似乎是不好的做法。

    [TestFixture]
    public class InterceptorTest : NhibernateSessionHelper
    {
    [Test]
    public void GetEntiy()
    {
        //ok trigger OnLoad in the Interceptor
        var user = GetSession().Get<User>(1);
        Assert.IsNotNull(user);
    }
    [Test]
    public void GetProjection()
    {
        var crit = GetSession().CreateCriteria<User>();
        crit.Add(Restrictions.Eq("Id", 5));
        crit.SetProjection(Projections.ProjectionList()
                                      .Add(Projections.Property("Id"), "Id")
                                      .Add(Projections.Property("Username"), "UserName"));
        crit.SetResultTransformer(Transformers.AliasToBean(typeof(LightweightUser)));
        //does not trigger the Interceptor
        var result = crit.List<LightweightUser>();
        Assert.IsNotNull(result.First());
    }
} 

    //Wire the Sessionfactory with Interceptor
    private static ISessionFactory CreateSessionFactory()
    {
        return new Configuration()
        .CurrentSessionContext<ThreadStaticSessionContext>()
        .SetInterceptor(new MyInterceptor())
            .Configure().BuildSessionFactory();
    }

 public class MyInterceptor: IInterceptor
{
    public override bool OnLoad(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types)
    {
        //do stuff
        var s = entity;
        return base.OnLoad(entity, id, state, propertyNames, types);
    }

Thanks in advance

在投影上使用NHibernate拦截器

拦截器的OnLoad方法只在处理preloaddevent时调用。在两种情况下会引发此问题:从数据库加载实体时,或从缓存组装实体时。用类似您的投影创建的对象不被认为是实体。

如果你想对实体和LightweightUser的元组应用相同的代码,你可以实现你的自定义IResultTransformer包含一个

的实例
Transformers.AliasToBean(typeof(LightweightUser))

和调用原始转换器方法后应用

的逻辑
//do stuff

如果你想了解更多关于拦截器的信息,我鼓励你阅读我的博客列表:http://blog.scooletz.com/2011/02/03/nhibernate-interceptor-magic-tricks-pt-1/