2011-09-21 69 views
1

如何使用NHibernate Criteria API來映射此SQL?如何從NHibernate的子查詢中進行選擇

SQL:

SELECT COUNT(*) FROM (
    SELECT FirstName, LastName FROM Employees GROUP BY FirstName, LastName 
) AS Query 

這是一個非常非常簡單的查詢,我的查詢有一個子查詢要複雜得多。

那麼,有什麼想法?

回答

2

我發現這個問題的解決方案,這是一個非常大的黑客攻擊,但它按預期工作。

我必須得到生成的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; 
} 
1
DetachedCriteria criteriaEmployees = DetachedCriteria.For<Employees>(); 
criteriaEmployees.SetProjection(Projections.CountDistinct("FirstName")); 
ICriteria executableCriteria = criteriaEmployees.GetExecutableCriteria(Session); 
int count = executableCriteria.UniqueResult<int>(); 
+0

這是我的解決方案。可悲的是,這並沒有真正的文件...所以如果你不知道它存在或錯誤地絆倒它,你有一個問題。 –