2009-11-29 69 views
0

我有一個NHibernate應用程序,當前使用SQL Server用戶定義函數。我想避免不得不調用這個函數,而是使用NH標準API來表達它的邏輯。不幸的是,我很難將NH文檔中的標準示例應用到我的特例中。所以我轉向這個網站尋求幫助。需要幫助將SQL轉換爲條件API

這是功能。它接受一個字符串參數並返回一個表。該函數在相同的兩個表格之間執行3個連接,但使用不同的連接標準,然後合併結果。

任何提示將不勝感激。提前致謝!

編輯:這是針對NH 2.1

編輯:在接受答案的註釋指出,轉換是不可能的,這是正確的答案

CREATE FUNCTION dbo.GetRevisionText 
(
    @LangId NVARCHAR(16) 
) 
RETURNS TABLE 
AS 
RETURN 
(
    SELECT r.RevisionId, 
    COALESCE(lp1.Title, lp2.Title, lp3.Title) Title, 
    COALESCE(lp1.Description, lp2.Description, lp3.Description) Description 
    FROM Revision r 
     LEFT JOIN LocalizedProperty lp1 
     ON lp1.RevisionId = r.RevisionId 
     AND lp1.LanguageId = @LangId 
     LEFT JOIN LocalizedProperty lp2 
     ON lp2.RevisionId = r.RevisionId 
     AND lp2.LanguageId = LEFT(@LangId, 2) 
     LEFT JOIN LocalizedProperty lp3 
     ON lp3.RevisionId = r.RevisionId 
     AND lp3.LanguageId = r.DefaultPropertiesLanguage 
); 

這裏是所涉及的3類的映射:

<class name="Revision"> 
    <id name="RevisionId" type="Guid"> 
    <generator class="assigned"/> 
    </id> 
    <set name="LocalizedProperties" inverse="true" lazy="true" cascade="all-delete-orphan"> 
    <key column="RevisionId"/> 
    <one-to-many class="LocalizedProperty"/> 
    </set> 
    <many-to-one name="DefaultPropertiesLanguage" class="Language" not-null="true"/> 
</class> 

<class name="Language"> 
    <id name="LanguageId" type="String" length="16"> 
    <generator class="assigned"/> 
    </id> 
    <property name="Lcid" type="Int32" unique="true" not-null="true"/> 
</class> 

<class name="LocalizedProperty" mutable="false"> 
    <composite-id> 
    <key-many-to-one name="Revision" class="Revision" column="RevisionId"/> 
    <key-many-to-one name="Language" class="Language" column="LanguageId"/> 
    </composite-id> 
    <property name="Title" type="String" length="200" not-null="true"/> 
    <property name="Description" type="String" length="1500" not-null="false"/> 
</class> 

回答

1

這可能做的工作(NH 1.2):但是,這並不產生ANSI語法

var crit = nhSes.CreateCriteria(typeof(Revision), "r") 
.SetProjection(
    Projections.SqlProjection(@"r.RevisionId as rid, 
    COALESCE(lp1.Title, lp2.Title, lp3.Title) as Title, 
    COALESCE(lp1.Description, lp2.Description, lp3.Description) as Description", new[] {"rid", "Title", "Description"}, new[] {NHibernateUtil.Guid, NHibernateUtil.String,NHibernateUtil.String}) 
); 

crit.CreateCriteria("LocalizedProperty", "lp1", JoinType.InnerJoin); 
crit.CreateCriteria("LocalizedProperty", "lp2", JoinType.InnerJoin); 
crit.CreateCriteria("LocalizedProperty", "lp3", JoinType.InnerJoin); 

crit.Add(Expression.Eq("lp1.LanguageId", langId)); 
crit.Add(Expression.Sql("lp2.LanguageId = LEFT(:LangId, 2)", langId, NHibernateUtil.String)); 
crit.Add(Expression.EqProperty("lp3.LanguageId", "r.DefaultPropertiesLanguage")); 

記加入但將約束置於WHERE子句中。我真的不認爲這是一個問題,你正在做一個內部連接,而不是一個外部連接。

另外我現在不記得在Expression.Sql上的正確參數符號。 我把它定義爲:LangId雖然它也可能是@LangId

旁註:你可以看到,雖然這是一個標準的查詢它只是一堆SQL語句的拆分所以符合標準的API;你確定這是你需要的嗎?

+0

感謝您的幫助,它給了我一個腿。不幸的是,它不工作:(NH抱怨「重複關聯路徑:LocalizedProperty」。我目前正在調查映射的第二和第三LocalizedProperty別名與視圖... – 2009-12-01 02:32:45

+0

你試過使用 crit.CreateAlias(「LocalizedProperty」 ,「lp1」); 它可能會拋出相同的錯誤,但你沒有什麼可以鬆動的 – Jaguar 2009-12-01 08:52:25

+0

就好像它不支持...檢查http://nhjira.koah.net/browse/NH-2016 .. 。如果你真的想將數據庫中的代碼移植到你的應用程序中,ISQLQuery是唯一的方法 – Jaguar 2009-12-01 09:03:28