虽然我多次从这个网站的集体智慧中受益,但这是我的第一个问题。
我有三个类似的话:
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的任务。但是这段代码需要来自DB的所有记录。对于每个ClassA最多有3条记录的ClassB,这可能不是问题,但对于具有数百条记录的ClassB,这意味着从DB中获取所有这些记录,只使用DB中每个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 :(得分: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
我想有更有效的答案,这将涉及分组。