NHibernate - 基于子属性过滤结果

3
我有这段代码,用于获取所有已启用的组及其子项。 我遇到的问题是子项也可以被禁用,但我无法让 fluent nhibernate 仅获取所有子项都启用的组。 我认为这是可能的,但该怎么做?
public class Group {
    public bool IsDisabled { get; set; }
    public string Description { get; set; }
    public ICollection<ChildType> Children { get; protected set; }
}

public class ChildType {
    public bool IsDisabled { get; set; }
    public string Description { get; set; }
}

public IList<Group> Search(string searchString) {
    IQueryOver<Group> query = Session.QueryOver<Group>()
        .WhereRestrictionOn(x => x.Description).IsInsensitiveLike(searchString, MatchMode.Start)
        .Where(x => !x.IsDisabled)
        .OrderBy(x => x.Description).Asc
        .Fetch(group => group.Children).Eager;

    return query
        .Cacheable()
        .List();
}

编辑:孩子和组之间存在N:M关系。

以下是我使用的解决方案:

public class Group {
    public long Id { get; set; }
    public bool IsDisabled { get; set; }
    public string Description { get; set; }
    public ICollection<ChildType> Children { get; protected set; }
}

public class ChildType {
    public long Id { get; set; }
    public bool IsDisabled { get; set; }
    public string Description { get; set; }
    public ICollection<Group> Groups { get; protected set; }
}

public IList<Group> Search(string searchString) {
    ChildType child = null;
    Group group = null;
    Group joinedGroup = null;

    var notDisabled = Session.QueryOver.Of<ExaminationType>()
        .Where(x => x.IsDisabled)
        .JoinAlias(x => x.Groups, () => joinedGroup )
            .Where(x => joinedGroup == group)
        .Select(x => x.Id);

    IQueryOver<Group> query = Session.QueryOver<Group>()
        .WhereRestrictionOn(x => x.Description).IsInsensitiveLike(searchString, MatchMode.Start)
        .JoinAlias(x => x.ExaminationTypes, () => child)
        .WithSubquery.WhereNotExists(notDisabled)
        .OrderBy(x => x.Description).Asc;

    return query
        .Cacheable()
        .List();
}
2个回答

5

你需要使用子查询来实现你想要的结果。但是为了做到这一点,你需要向ChildType实体添加一个Group引用。

Group group = null;
var childCrit = QueryOver.Of<ChildType>()
        .Where(c => c.Group == group).And(c => c.IsDisabled)
        .Select(c => c.Id);
var query = Session.QueryOver(() => group)
        .WhereRestrictionOn(x => x.Description).IsInsensitiveLike(searchString, MatchMode.Start)
        .Where(x => !x.IsDisabled)
        .WithSubquery.WhereNotExists(childCrit)
        .OrderBy(x => x.Description).Asc
        .Fetch(group => group.Children).Eager;

这将获取所有未禁用且没有禁用子级的组。


在组和子项之间存在N:M关系,使得子查询有点烦人,但如果我解决了这个问题,我想这就是我要使用的解决方案。谢谢! - Fredrik C
对于子查询,您只需要使用“Select”进行投影即可。 - Vadim

1
public IList<Group> Search(string searchString) {

    Children children = null;

    IQueryOver<Group> query = Session.QueryOver<Group>()
        .WhereRestrictionOn(x => x.Description).IsInsensitiveLike(searchString, MatchMode.Start)
        .Where(x => !x.IsDisabled)
        .JoinAlias(x => x.Children, () => children)
            .Where(x => !x.IsDisabled)
        .OrderBy(x => x.Description).Asc;

    return query
        .Cacheable()
        .List();
}

那应该做你想做的事。

加入别名也会为您提取它。

http://www.philliphaydon.com/2011/04/nhibernate-querying-relationships-are-depth/


在将 .Where(x => !x.IsDisabled) 更改为 .Where(x => !children.IsDisabled) 之后,我让它工作了一下,但我获得的是如果任何孩子被启用,则获取分组,而不是所有孩子都被启用。 - Fredrik C
@Fredrik - 哦,抱歉我读错了。我认为你需要使用exists,所以查询所有启用的子项中没有禁用的子项,返回组,然后在之前的查询上使用WithSubquery.Exists查询组。http://www.philliphaydon.com/2011/01/revisiting-exists-in-nhibernate-3-0-and-queryover/ - 我真的需要睡觉了,因为明天还要工作,我会考虑一下查询的样子,然后回复你。 - Phill
谢谢你的帮助,但我使用了Vadim建议的解决方案。 - Fredrik C
@Fredrik - 没错,太棒了,他昨晚想到的正是我想的那个,只不过用的是not-exists,这很有道理。 - Phill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接