2010-03-17 45 views
1

我有一個奇怪的要求,我的客戶強加給我。他們有他們花費了大量的時間來優化的工作如下某些查詢:NHibernate:自定義標準來操縱連接

  1. 存儲過程建立了一個「ID列表」,這基本上代表了「去哪兒」過濾
  2. 的ID列表被加入到您的數據表

的ID列表將是這個樣子

IdListTable.Customers_Id

1087, 
10094, 
87, 
1077 
因此

的連接查詢看起來像:

SELECT c.Id, c.FirstName, c.LastName 
FROM Customers c INNER JOIN IdListTable idList ON (c.Id = idList.Customers_Id); 

我希望能夠做這樣的事在NHibernate的

IEnumerable<Customer> GetMatching(Specification spec) { 
    string idListName = "IdListTable"; 

    _idListGenerator.BuildIdList(idListName); 

    return _session.CreateCriteria<Customer>(). 
    Add(new JoinIdListCriterion(idListName) 
    .Enumerable<Customer>() 
} 

所以首先,這是正確的概念?我想要實現自己的ICriterion還是完全用於其他事情?其次,我該如何做到這一點。我已經嘗試過實現AbstractCriterion並閱讀doc-comments,我只是不確定我會在哪裏查詢構建過程。

回答

1

最好的辦法是將「id-list」表添加到映射中,這樣就可以像任何其他表一樣執行連接。

另一種選擇是執行連接的WHERE子句,所以你會得到這樣的:

SELECT c.Id, c.FirstName, c.LastName 
FROM Customers c WHERE c.Id IN (SELECT Customers_Id FROM IdListTable); 

你可以把它的工作使用SqlCriteria:

return _session.CreateCriteria<Customer>("c") 
    .Add(Expression.Sql("c.Id IN (SELECT Customers_Id FROM IdListTable)", new object[0], new IType[0])) 
    .Enumerable<Customer>(); 
+0

謝謝,但我不想映射id列表,因爲它不是一個實體。一個IN查詢是這樣做的一種方式,當然,但我真的想把它作爲一個Join來工作。 ICriterion似乎揭露了這一點,但我不確定如何。 – 2010-03-17 19:27:34

+0

嘿法比奧,這將如何與緩存,交易等工作。看起來好像沒有辦法,NHibernate可以在這些方面做任何事情,你會放棄使用它開始的許多好處。 – 2010-03-17 20:13:01

+0

緩存和事務應該仍然正常工作,我在一些項目中使用了Expression.Sql,並且從來沒有任何問題。至於加入,只要你使用標準API,你必須映射所有的表(這就是爲什麼你可能應該映射IdListTable,即使它不是一個實體,它仍然是你模型的一個重要部分),或者嘗試使用IN子句或某些用戶定義的函數「劫持」您的查詢。另一個選擇是使用純SQL編寫此特定查詢(通過使用_session.CreateSQLQuery())。 – 2010-03-17 22:31:26