如何从项列表中批量获取子属性?

时间:2012-03-27 15:46:46

标签: c# nhibernate fluent-nhibernate queryover

我有一个搜索方法,它返回多个项目,每个项目都有几个子属性,并引用了其他表格。 对于作为集合的子属性,一切都按照我的要求进行,但是如何为一对一的孩子做同样的事情呢?

这是一些存根和我尝试过的一些代码:

public class Request {
    //HasMany(x => x.Examinations).Access.CamelCaseField().Cascade.All().BatchSize(100);
    public virtual IList<Examination> Examinations;

    //References(x => x.Creator, "rem_creator_userid");
    public virtual User Creator { get; private set; }
}

public class RepositoryExample {

    // This search will ask one nice-looking query to the database fetchning all the
    // requests
    // Then it will ask ONE query fetching the Examinations from the database
    // Then it will ask N+1 questions fetching Creator from all Requests
    public IList<Request> Search1(ListRequestSearchConditions searchConditions) {
        var query =
            from request in Session.Query<Request>()
            from exam in request.Examinations
            where
                searchConditions.Units.Contains(request.ReferralSource) &&
                exam.Status.HasValue &&
                exam.Status.Value >= ExaminationStatus.Value.RequestSubmitted &&
                request.PatientId != null
            select request;

        return query
            .Skip((searchConditions.Page - 1) * searchConditions.PageSize)
            .Take(searchConditions.PageSize)
            .ToList();
    }

    // This search with ask one slow join-query fetching everything from the database
    public IList<Request> Search2(ListRequestSearchConditions searchConditions) {
            Examination examinationAlias = null;

        return Session.QueryOver<Request>()
            .WhereRestrictionOn(request => request.ReferralSource).IsIn(searchConditions.Units)
            .Where(request => request.PatientId != null)
            .JoinAlias(request => request.Examinations, () => examinationAlias)
            .Where(() => examinationAlias.Status.Value != null)
            .Where(() => examinationAlias.Status.Value >= ExaminationStatus.Value.RequestSubmitted)
            .Skip((searchConditions.Page - 1) * searchConditions.PageSize)
            .Take(searchConditions.PageSize)
            .ToList();
    }

    // This search will first ask ONE query joining Request with Examinations
    // Then it will ask ONE query fetching the Examinations from the database
    // Then it will ask N+1 queries fetching Creator from all Requests
    public IList<Request> Search3(ListRequestSearchConditions searchConditions) {
            Examination examinationAlias = null;

        return Session.QueryOver<Request>()
            .WhereRestrictionOn(request => request.ReferralSource).IsIn(searchConditions.Units)
            .Where(request => request.PatientId != null)
            .JoinAlias(request => request.Examinations, () => examinationAlias)
            .Where(() => examinationAlias.Status.Value != null)
            .Where(() => examinationAlias.Status.Value >= ExaminationStatus.Value.RequestSubmitted)
            .Fetch(request => request.Examinations).Lazy
            .Fetch(request => examinationAlias.ExaminationType).Lazy;
            .Skip((searchConditions.Page - 1) * searchConditions.PageSize)
            .Take(searchConditions.PageSize)
            .ToList();
    }
}

我希望可以在3个查询中执行此操作,一个获取请求列表,一个获取考试,一个获取创建者。

2 个答案:

答案 0 :(得分:1)

如果您不想将它放在一个查询中(在LINQ中使用Fetch / ThenFetch)并使用批处理,则必须在Creator映射级别指定它。无法在查询级别定义批量大小。

在Fluent NHibernate中,您只需在BatchSize(100)映射中添加Creator即可。

答案 1 :(得分:0)

一次性往返

// determine the requests
var subquery = QueryOver.Of<Request>()
    .WhereRestrictionOn(request => request.ReferralSource).IsIn(searchConditions.Units)
    .Where(request => request.PatientId != null)
    .JoinQueryOver(request => request.Examinations)
    .Where(examination => examination.Status.Value != null)
    .Where(examination => examinationAlias.Status.Value >= ExaminationStatus.Value.RequestSubmitted)
    .Skip((searchConditions.Page - 1) * searchConditions.PageSize)
    .Take(searchConditions.PageSize)
    .Select(r => r.Id);

// load the requests with eagerly fetching the associations
var results = Session.QueryOver<Request>()
    .WithSubquery.WhereProperty(request => request.Id).In(subquery)
    .Fetch(request => request.Creator).Eager
    .Fetch(request => request.Examinations).Eager
    .ToList();