NHibernate:有没有办法从Criteria获取HQL或SQL?

时间:2014-12-23 10:19:12

标签: c# sql nhibernate hql

我认为有时我们希望从标准中获取HQLSQL。请看以下示例: 假设我们想要在-id列表中删除T类型的所有对象:

public class Repostiroy<T>
{
     public void Delete(object[] ids){...}

}

我知道我们可以像这样实现它:

Session.CreateQuery<T>(String.Format("from {0} where id in(:ids)",typeof(T).Name).SetListParameter("ids",ids).ExecuteUpdate();

但是对于泛型方法,它可能存在一些问题(例如,类型名称和id字段名称)。 当您在NHibernate中使用Criteria时,它将为您生成HQLSQL但我不知道从Criteria中提取它的方法。假设我们有一个名为ToHQL的方法标准我们可以这样做:

Session.CreateQuery<T>("delete "+Session.CreateCriteria<T>().Add(Restrictions.In(Projections.Id(),ids)).ToHQL()).ExecuteUpdate();

问题是如何实施ToHQLToSQL

更新

可以对Session.Query<T>应用相同的方法,您可以使用NHibernate Linq Provider为您创建HQL和/或SQL

1 个答案:

答案 0 :(得分:0)

通过深入了解NHibernate,我设法为Criteria写了两个扩展:

<强> ToISqlCommands:

public static IEnumerable<ISqlCommand> ToISqlCommands(this ICriteria criteria)
        {
            var criteriaImp = criteria as CriteriaImpl;
            if (criteriaImp == null)
                throw new InvalidOperationException();
            var implementors = criteriaImp.Session.Factory.GetImplementors(criteriaImp.EntityOrClassName);
            var loaders = new CriteriaLoader[implementors.Length];
            for (var i = 0; i < implementors.Length; i++)
            {
                loaders[i] = new CriteriaLoader((IOuterJoinLoadable) typeof(SessionImpl).GetMethod("GetOuterJoinLoadable",BindingFlags.Instance | BindingFlags.NonPublic).Invoke(criteriaImp.Session,new object[]{implementors[i]}), criteriaImp.Session.Factory, criteriaImp, implementors[i], criteriaImp.Session.EnabledFilters);
            }

            return
                loaders.Select(
                    loader => loader.CreateSqlCommand(loader.Translator.GetQueryParameters(), criteriaImp.Session));
        }

ToIDbCommnads:

public static IEnumerable<IDbCommand> ToIDbCommands(this ICriteria criteria)
        {
             var criteriaImp = criteria as CriteriaImpl;
            if (criteriaImp == null)
                throw new InvalidOperationException();
            var implementors = criteriaImp.Session.Factory.GetImplementors(criteriaImp.EntityOrClassName);
            var loaders = new CriteriaLoader[implementors.Length];
            for (var i = 0; i < implementors.Length; i++)
            {
                loaders[i] = new CriteriaLoader((IOuterJoinLoadable) typeof(SessionImpl).GetMethod("GetOuterJoinLoadable",BindingFlags.Instance | BindingFlags.NonPublic).Invoke(criteriaImp.Session,new object[]{implementors[i]}), criteriaImp.Session.Factory, criteriaImp, implementors[i], criteriaImp.Session.EnabledFilters);
            }

            return
                loaders.Select(
                    loader => (IDbCommand)loader.GetType().GetMethod("PrepareQueryCommand", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(loader,new object[]{ loader.Translator.GetQueryParameters(),false, criteriaImp.Session}));
        }

这些扩展并不是我真正想到的,但他们可以做到这一点。 ISqlCommand是一个NHibernate接口,其中包含sql查询及其查询参数定义。

<强>更新

仍在使用NHibernate Linq Provider