2013-02-20 32 views
2

雖然我多次從本網站的集體智慧中受益,但這是我的第一個問題。如何從一般關係中只返回一個具體項目

我有,比方說,三類像這樣:

public class ClassA 
{ 
    public ClassA() {} 

    public virtual IList<ClassB> ClassBs { get; set; } 
} 

public class ClassB 
{ 
    public ClassB() {} 

    public virtual DateTime StartDate { get; set; } 
    public virtual DateTime? EndDate { get; set; } 
    public virtual ClassC SomeObject { get; set; } 
} 

public class ClassC 
{ 
    public ClassC() {} 

    public virtual string Name { get; set; } 
} 

我使用NHibernate(3.3.1.4)和FluentNHibernate(1.3.0.733),並映射文件是:

public Class ClassAMap : ClassMap<ClassA> 
{ 
    HasMany(x => x.ClassBs); 
} 

public Class ClassBMap : ClassMap<ClassB> 
{ 
    Map(x => x.StartDate).Not.Nullable(); 
    Map(x => x.EndDate).Nullable(); 
    References(x => x.SomeData).Not.Nullable(); 
} 

public Class ClassCMap : ClassMap<ClassC> 
{ 
    Map(x => x.Name).Not.Nullable(); 
} 

也有ID和版本,但我不知何故認爲它們是不相關的。

我想要做的是:

select all "SomeObject"s from ClassBs of all "ClassA"s which have their "EndDate"s null and which have the most current StartDate in their group. 

我嘗試了一些玩弄QueryOver但我能得到最多的是一個IList<IList<ClassB>>這實在是遠不是我要完成。

編輯: (我認爲)下面的代碼與Linq完成任務。但是這個代碼需要來自數據庫的所有記錄。對於每個ClassA具有多達3條記錄或者具有幾百條記錄的ClassB的ClassB,這可能不成問題,這意味着從數據庫獲取所有這些記錄僅使用來自數據庫中每個ClassA的ClassB的一條記錄。

IList<ClassC> classCLs = new List<ClassC>(); 
ClassB latest = null; 
foreach (
    IList<ClassB> classBLs in 
     Session.QueryOver<ClassA>() 
      .Select(c => c.ClassBs).List<IList<ClassB>>() 
) { 
    latest = classBLs.Where(cB => cB.EndDate == null).Aggregate((curr, next) => next.StartDate > curr.StartDate ? next : curr); 
    if (latest != null && !classCLs.Contains(latest.SomeObject)) { 
     classCLs.Add(latest.SomeObject); 
    } 
} 

回答

0

假設你已經的ClassA id屬性,也許這涉及一個子查詢,可以有一定的幫助:

ClassA aAlias = null; 
ClassB bAliasMax = null, bAlias = null; 

var subQuery = QueryOver.Of<ClassA>().JoinAlias(a => a.ClassBs,() => bAliasMax) 
         .Where(Restrictions.On(() => bAliasMax.EndDate).IsNotNull) 
         .Where(a=>a.Id==aAlias.Id) 
         .Select(Projections.Max(() => bAliasMax.StartDate)); 

var result = 
    _laSession.QueryOver(() => aAlias) 
       .JoinAlias(a => a.ClassBs,() => bAlias) 
       .WithSubquery.WhereProperty(() => bAlias.StartDate).Eq(subQuery) 
       .Select(Projections.Property(() => bAlias.SomeObject)) // suggested adding from question's author 
       .List<ClassC>(); // see above 

我想有更有效的答案,這將涉及分組。

+0

這將返回一個由兩個表(ClassA和ClassB)組成的對象。我添加了'.Select(Projections.Property(()=> bAlias.SomeObject))'以'.WithSubquery ...'開頭並將'List()'更改爲'List ()' – mevtagezer 2013-02-21 13:51:34

+0

@mevtagezer好吧,沒有意識到「SomeObject」提到了classC的「SomeObject」,並且只是讀了「ClassB的所有對象」;-) – jbl 2013-02-21 14:06:37

+0

如果您編輯您的答案,我會將其標記爲已接受。謝謝。 – mevtagezer 2013-02-21 14:23:19

相關問題