2

私はこのサイトの集合的な知恵から何度も恩恵を受けてきましたが、これはここでの最初の質問です.

たとえば、次のような 3 つのクラスがあります。

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 から 1 つのレコードのみを使用することを意味します。

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);
    }
}
4

1 に答える 1

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

グループ化を含む、より効果的な答えがあると思います。

于 2013-02-21T10:36:22.647 に答える