2012-08-14 36 views
5

我試圖連接使用JoinAlias的幾個實體,並且無法弄清楚如何獲取多個連接。下面的代碼導致SQL錯誤:NHibernate QueryOver多重連接別名,只有第一個生成連接

[TestMethod] 
public void TestAliases() 
{ 
    App_Start.NHibernateProfilerBootstrapper.PreStart(); 

    var type = new ShirtStyleType {Id = 1}; 
    var style = new ShirtStyle {Id = 1, ShirtStyleType = type}; 
    var shirt = new Shirt {Id = 1}; 
    var shirtStyle = new ShirtShirtStyle {Shirt = shirt, ShirtStyle = style}; 
    shirt.ShirtStyles = new[] {shirtStyle}; 

    using (Session.BeginTransaction()) 
     Session.Save(shirt); 

    Session.Clear(); 

    using (Session.BeginTransaction()) 
    { 
     Shirt shirtAlias = null; 
     ShirtShirtStyle shirtStylesAlias = null; 
     ShirtStyle shirtStyleAlias = null; 
     ShirtStyleType shirtStyleTypeAlias = null; 

     var query = Session.QueryOver<Shirt>(() => shirtAlias) 
      .JoinAlias(() => shirtAlias.ShirtStyles,() => shirtStylesAlias) 
      .JoinAlias(() => shirtStylesAlias.ShirtStyle,() => shirtStyleAlias) 
      .JoinAlias(() => shirtStyleAlias.ShirtStyleType,() => shirtStyleTypeAlias) 
      .Where(() => shirtStyleTypeAlias.Id == 1) 
      .List(); 
    } 
} 

錯誤:

ERROR: 
SQLite error 
no such column: shirtstyle3_.Id 

導致錯誤的SQL:

SELECT this_.Id    as Id0_1_, 
     shirtstyle1_.Shirt  as Shirt1_0_, 
     shirtstyle1_.ShirtStyle as ShirtStyle1_0_ 
FROM "Shirt" this_ 
     inner join "ShirtShirtStyle" shirtstyle1_ 
     on this_.Id = shirtstyle1_.Shirt_id 
WHERE shirtstyle3_.Id = 1 /* @p0 */ 

這是非常明顯的看出爲什麼錯誤發生 - 查詢缺少連接,特別是除「ShirtShirtStyle」之外的每個連接。從我對JoinAlias的理解,我提供的代碼應該加入必要的表格,但它不是,我不明白爲什麼。在這種情況下,有什麼需要讓JoinAlias工作?

我爲這個測試創建的實體和映射如下,以防它們與它們的映射方式有關。

實體:

public class Shirt 
{ 
    public virtual int Id { get; set; } 
    public virtual IList<ShirtShirtStyle> ShirtStyles { get; set; } 
} 

public class ShirtShirtStyle 
{ 
    public virtual Shirt Shirt { get; set; } 
    public virtual ShirtStyle ShirtStyle { get; set; } 

    protected bool Equals(ShirtShirtStyle other) 
    { 
     return Equals(Shirt, other.Shirt) && Equals(ShirtStyle, other.ShirtStyle); 
    } 

    public override bool Equals(object obj) 
    { 
     if (ReferenceEquals(null, obj)) return false; 
     if (ReferenceEquals(this, obj)) return true; 
     if (obj.GetType() != this.GetType()) return false; 
     return Equals((ShirtShirtStyle) obj); 
    } 

    public override int GetHashCode() 
    { 
     unchecked 
     { 
      return ((Shirt != null ? Shirt.GetHashCode() : 0)*397)^(ShirtStyle != null ? ShirtStyle.GetHashCode() : 0); 
     } 
    } 
    } 

    public class ShirtStyle 
    { 
     public virtual int Id { get; set; } 
     public virtual ShirtStyleType ShirtStyleType { get; set; } 
    } 

    public class ShirtStyleType 
    { 
     public virtual int Id { get; set; } 
    } 

地圖:

public class ShirtMap : ClassMap<Shirt> 
{ 
    public ShirtMap() 
    { 
     Id(x => x.Id).GeneratedBy.Assigned(); 
     HasMany(x => x.ShirtStyles); 
    } 
} 

public sealed class ShirtShirtStyleMap : ClassMap<ShirtShirtStyle> 
{ 
    public ShirtShirtStyleMap() 
    { 
     CompositeId() 
      .KeyReference(x => x.Shirt) 
      .KeyReference(x => x.ShirtStyle); 
    } 
} 

public sealed class ShirtStyleMap : ClassMap<ShirtStyle> 
{ 
    public ShirtStyleMap() 
    { 
     Id(x => x.Id).GeneratedBy.Assigned(); 
     References(x => x.ShirtStyleType); 
    } 
} 

public sealed class ShirtStyleTypeMap : ClassMap<ShirtStyleType> 
{ 
    public ShirtStyleTypeMap() 
    { 
     Id(x => x.Id).GeneratedBy.Assigned(); 
    } 
} 
+0

我的猜測是你應該使用JoinQueryOver代替JoinAlias。 – 2012-08-14 22:49:08

回答

2

那麼這個查詢似乎只是按預期 - 這個問題看起來是與功能NHibernate。即使引用是通過.KeyReference在複合實體上指定的,您需要明確地在映射中根據https://stackoverflow.com/a/10995486/981205重新指定它們。不知道這是一個錯誤還是預期的行爲。

+0

謝謝你,我以爲我瘋了。令人討厭的是,只有在使用查詢結束時纔會出現問題,如果使用linq,則nhibernate會創建連接。問題是我需要外部連接,因此我必須使用查詢... – setebos 2013-04-13 00:51:55