我认为有时我们希望从标准中获取HQL
或SQL
。请看以下示例:
假设我们想要在-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时,它将为您生成HQL
和SQL
但我不知道从Criteria中提取它的方法。假设我们有一个名为ToHQL
的方法标准我们可以这样做:
Session.CreateQuery<T>("delete "+Session.CreateCriteria<T>().Add(Restrictions.In(Projections.Id(),ids)).ToHQL()).ExecuteUpdate();
问题是如何实施ToHQL
和ToSQL
?
更新
可以对Session.Query<T>
应用相同的方法,您可以使用NHibernate Linq Provider
为您创建HQL
和/或SQL
答案 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