如何使用NHibernate Criteria API來映射此SQL?如何從NHibernate的子查詢中進行選擇
SQL:
SELECT COUNT(*) FROM (
SELECT FirstName, LastName FROM Employees GROUP BY FirstName, LastName
) AS Query
這是一個非常非常簡單的查詢,我的查詢有一個子查詢要複雜得多。
那麼,有什麼想法?
如何使用NHibernate Criteria API來映射此SQL?如何從NHibernate的子查詢中進行選擇
SQL:
SELECT COUNT(*) FROM (
SELECT FirstName, LastName FROM Employees GROUP BY FirstName, LastName
) AS Query
這是一個非常非常簡單的查詢,我的查詢有一個子查詢要複雜得多。
那麼,有什麼想法?
我發現這個問題的解決方案,這是一個非常大的黑客攻擊,但它按預期工作。
我必須得到生成的SQL並用SELECT COUNT(*)查詢包圍它。這裏是代碼要做到這一點:
public ISQLQuery BuildCountQuery(ICriteria criteria)
{
CriteriaImpl c = (CriteriaImpl)criteria;
SessionImpl s = (SessionImpl)c.Session;
string entityOrClassName = ExtractRealClassName(c);
SessionFactoryImpl factory = (SessionFactoryImpl)s.SessionFactory;
String[] implementors = factory.GetImplementors(entityOrClassName);
string implementor = implementors.Length == 0 ? null : implementors[0];
var persister = (IOuterJoinLoadable)factory.GetEntityPersister(implementor);
CriteriaLoader loader = new CriteriaLoader(persister, factory, c, implementor, s.EnabledFilters);
SqlString sql = loader.SqlString.Insert(0, "SELECT COUNT(*) FROM (");
sql = sql.Append(") AS Query");
var parameters = loader.Translator.CollectedParameters;
var sqlQuery = this.session.CreateSQLQuery(sql.ToString());
for (int i = 0; i < parameters.Count; i++)
sqlQuery.SetParameter(i, parameters.ElementAt(i).Value, parameters.ElementAt(i).Type);
return sqlQuery;
}
private string ExtractRealClassName(CriteriaImpl criteria)
{
Type rootEntityType = criteria.GetRootEntityTypeIfAvailable();
if (rootEntityType.GetInterfaces().Contains(typeof(INHibernateProxy)))
return criteria.GetRootEntityTypeIfAvailable().BaseType.FullName;
else
return criteria.EntityOrClassName;
}
DetachedCriteria
可用於創建子查詢。一些示例在documentation中。
DetachedCriteria criteriaEmployees = DetachedCriteria.For<Employees>();
criteriaEmployees.SetProjection(Projections.CountDistinct("FirstName"));
ICriteria executableCriteria = criteriaEmployees.GetExecutableCriteria(Session);
int count = executableCriteria.UniqueResult<int>();
這是我的解決方案。可悲的是,這並沒有真正的文件...所以如果你不知道它存在或錯誤地絆倒它,你有一個問題。 –