C# NHibernate拦截器在投影上的使用

C# NHibernate拦截器在投影上的使用,c#,interceptor,nhibernate-criteria,nhibernate-projections,C#,Interceptor,Nhibernate Criteria,Nhibernate Projections,我有这样的情况: 我使用Nhibernate映射一个实体“User”,该实体在Sql中映射到一个大表上,出于性能原因,我创建了一个轻量级实体“LightweightUser”,该实体只有一小部分属性,并且未映射到hbm文件或其他文件中,我正在使用Nhibernate投影技术连接'LightweightUser'实体。这两个实体都派生自包含Id属性的简单类“实体” 上述实现工作正常,sql查询更小==更快 但在我的Nhibernate会话工厂中,我还注入了一个Nhibernate Intercor

我有这样的情况:

我使用Nhibernate映射一个实体“User”,该实体在Sql中映射到一个大表上,出于性能原因,我创建了一个轻量级实体“LightweightUser”,该实体只有一小部分属性,并且未映射到hbm文件或其他文件中,我正在使用Nhibernate投影技术连接'LightweightUser'实体。这两个实体都派生自包含Id属性的简单类“实体”

上述实现工作正常,sql查询更小==更快

但在我的Nhibernate会话工厂中,我还注入了一个Nhibernate Intercorper。 当我从NHibernate Dao获取“用户”实体时,会调用拦截器的OnLoad方法,但当我从NHibernate Dao获取“轻量级用户”实体时,拦截器不会被触发(OnLoad方法)

这可能与NHibernate SessionFactory不了解我的“LightweightUser”实体有关。有没有办法通知Sessionfactory/拦截器我的“轻量级”实体的存在?或者有没有其他技术将投影线连接到拦截器上?是的,我也可以为我的轻量级实体复制“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);
    }
[TestFixture]
公共类拦截器测试:NhibernateSessionHelper
{
[测试]
公共空间
{
//拦截器中的ok触发器OnLoad
var user=GetSession().Get(1);
Assert.IsNotNull(用户);
}
[测试]
公共投影()
{
var crit=GetSession().CreateCriteria();
标准添加(限制条件等式(“Id”,5));
crit.SetProjection(Projections.ProjectionList()
.Add(Projections.Property(“Id”),“Id”)
.Add(Projections.Property(“用户名”),“用户名”);
crit.SetResultTransformer(Transformers.AliasToBean(typeof(LightweightUser)));
//不会触发拦截器
var result=crit.List();
Assert.IsNotNull(result.First());
}
} 
//用拦截器连接Sessionfactory
私有静态ISessionFactory CreateSessionFactory()
{
返回新配置()
.CurrentSessionContext()
.SetInterceptor(新的MyInterceptor())
.Configure().BuildSessionFactory();
}
公共类MyInterceptor:IInterceptor
{
public override bool OnLoad(对象实体、对象id、对象[]状态、字符串[]属性名称、NHibernate.Type.IType[]类型)
{
//做事
var s=实体;
返回base.OnLoad(实体、id、状态、属性名称、类型);
}

提前感谢

拦截器的OnLoad方法仅在处理PreLoadEvent时调用。这在两种情况下出现:从数据库加载实体时,或从缓存组装实体时。使用类似您的投影创建的对象不被视为实体

如果希望为实体和LightweightUser的元组应用相同的代码,则可以实现包含实例的自定义IResultTransformer

Transformers.AliasToBean(typeof(LightweightUser))
调用原始transformer方法后,应用

//do stuff
如果想了解更多关于interceptor的信息,我建议您阅读我的博客条目列表,从这里开始: