2012-02-15 73 views
5

我有以下兩個表:NHibernate的 - 左加入

喬布斯 areaID表示,JobNo(複合鍵)

日誌 LOGID,areaID表示,JobNo

我需要得到所有作業沒有任何與他們關聯的日誌。在SQL我可以這樣做:

SELECT Jobs.AreaID, 
     Jobs.JobNo 
FROM Jobs 
     LEFT JOIN Logs 
      ON Jobs.AreaID = Logs.AreaID 
      AND Jobs.JobNo = Logs.JobNo 
WHERE Logs.LogID is null 

但我不知道如何使用NHibernate完成此操作。任何人都可以提供任何指針?

這裏是我的映射:

<class name="Job" table="Jobs"> 
    <composite-key name="Id"> 
     <key-property name="JobNo"/> 
     <key-many-to-one name="Area" class="Area" column="AreaID"/> 
    </composite-key> 
</class> 

<class name="Log" table="Logs"> 
    <id name="Id" column="LogID"> 
     <generator class="identity"/> 
    </id> 
    <property name="JobNo"/> 
    <many-to-one name="Area" class="Area" column="AreaID"/> 
</class> 

感謝

更新

OK,我修改Nosila的輕微的答案,這是現在在做什麼,我想:

Log logs = null; 

return session.QueryOver<Job>() 
    .Left.JoinAlias(x => x.Logs,() => logs) 
    .Where(x => logs.Id == null) 
    .List<Job>(); 

我也不得不將這添加到我的工作中映射:

<bag name="Logs"> 
    <key> 
     <column name="JobNo"></column> 
     <column name="DivisionID"></column> 
    </key> 
    <one-to-many class="Log"/> 
</bag> 

感謝您的幫助。 :)

+0

你可以發佈你現在查詢? – Nosila 2012-02-15 12:40:12

+0

上面的SQL查詢是我正在使用的。我現在剛學習NH,並試圖將小應用程序轉換爲使用它。 – Tom 2012-02-15 12:48:20

+0

你有你的映射創建?另外,有人糾正我,如果我錯了,但我認爲你需要NHibernate 3.2爲你的連接添加條件(無論如何使用'QueryOver' API)。 – Nosila 2012-02-15 12:52:14

回答

6

我不熟悉組合標識符,因爲我不使用它們,所以我知道NHibernate會自動創建正確的左連接。無論如何,下面的(未測試)查詢應該讓你開始。

Job jobAlias = null; 
Log logAlias = null; 
YourDto yourDto = null; 

session.QueryOver<Job>() 
    // Here is where we set what columns we want to project (e.g. select) 
    .SelectList(x => x 
     .Select(x => x.AreaID).WithAlias(() => jobAlias.AreaID) 
     .Select(x => x.JobNo).WithAlias(() => jobAlias.JobNo) 
    ) 
    .Left.JoinAlias(x => x.Logs,() => logAlias, x.JobNo == logAlias.JobNo) 
    .Where(() => logAlias.LogID == null) 
    // This is where NHibernate will transform what you have in your `SelectList()` to a list of objects 
    .TransformUsing(Transformers.AliasToBean<YourDto>()) 
    .List<YourDto>(); 

public class YourDto 
{ 
    public int AreaID { get; set; } 
    public int JobNo { get; set; } 
} 

注意:您需要NHibernate 3.2來設置連接條件。

+1

謝謝。我必須仔細考慮這一點(其中有一些錯誤)。對於這樣一個簡單的查詢,它似乎也非常複雜。 – Tom 2012-02-15 13:25:15

+0

@Tom我同意這種複雜性,在SQL中編寫它會簡單得多。我覺得ORM抽象正在失控。 – Jafin 2012-08-09 04:16:37

4
Job job = null; 
var jobsWithoutLogs = session.QueryOver(() => job) 
    .WithSubquery.WhereNotExists(QueryOver.Of<Log>() 
     .Where(log => log.Job == job) 
     .Select(Projections.Id())) 
    .List() 

更新:我看到你添加了映射。上面的代碼只適用於以下映射

<class name="Log" table="Logs"> 
    <id name="Id" column="LogID"> 
     <generator class="identity"/> 
    </id> 
    <many-to-one name="Job" > 
     <column name="JobNo"/> 
     <column name="AreaID"/> 
    <many-to-one /> 
</class> 
+0

不錯。我更喜歡這個解決方案。 – Nosila 2012-02-15 13:08:07

+0

這似乎更容易,雖然我得到錯誤「不能使用沒有投影的條件上的子查詢」。此外,這是一個更昂貴的查詢,因爲它使用子查詢而不是簡單的左連接? – Tom 2012-02-15 13:24:30

+0

1)增加投影。 2)我不認爲它做同樣的事情會更昂貴。您可以查看查詢計劃 – Firo 2012-02-16 05:54:39