QueryOver <t>上的析取总是指根实体</t>

时间:2011-03-29 14:38:36

标签: nhibernate queryover

我正在尝试使用析取函数在X个实体上添加一定数量的OR条件,这些实体实现了包含日期信息的特定接口。我的问题是,当生成SQL时,我所有的析取条件都指向QueryOver的根实体。

我创建了一个添加条件的通用方法

    public static QueryOver<T,T2> AddChangedCondition<T,T2>(this QueryOver<T,T2> query, DateTime from, DateTime to, Disjunction disjunction) where T2 : IHaveDate
    {
        if(disjunction == null )
            disjunction = new Disjunction();

        disjunction.Add<T2>(k => (k.DeleteDate > from && k.DeleteDate  < to)
                || k.CreatedDate > from
                || k.UpdatedDate > from);

        return query;
    }

我想这样用:

Disjunction disjunction = null;
var query = QueryOver.Of<User>()
    .AddChangedCondition(fromDate,toDate, disjunction)
    .JoinQueryOver<Program>(user => user.Programs)
        .AddChangedCondition(fromDate,toDate, disjunction);

query.Where(disjunction);

从中生成的SQL将看起来像

select ....
from User
where
(
    (
        this_.raderadDatum > @p1 
        and this_.raderadDatum < @p2
    ) 
    or this_.skapadDatum > @p3 
    or this_.uppdateradDatum > @p4
    )
or
    (
        this_.raderadDatum > @p1 
        and this_.raderadDatum < @p2
    ) 
    or this_.skapadDatum > @p3 
    or this_.uppdateradDatum > @p4
    )

我尝试过使用别名的不同解决方案,但没有成功。任何帮助都会很棒!

3 个答案:

答案 0 :(得分:4)

尝试这种方式,我插入了一些随机条件,我使用了别名

 var qOver = _session.QueryOver<User>(() => usr)         
     .JoinAliases(() => usr.Programs, prg, JoinType.LeftOuterJoin)
     .Where(Restrictions.Or(
                Restrictions.On(() => usr.ID).IsIn(MyValue)
                ,Restrictions.Or(
                   Restrictions.On(() => prg.ID).IsIn(MyValue)
                  , Restrictions.On(() => prg.ID).IsNull)
                 )
               )
     .List<User>();

通过这种方式,您的SQL代码将是以下

SELECT ....
FROM User
INNER JOIN Program On (...conditions...)
WHERE User.ID = 'MyValue'
OR (Program.ID IN ('Value1','Value2') OR Program.ID IS NULL)

我希望它有用

答案 1 :(得分:4)

你可以绕过@Faber在answer中建议的神奇字符串。

我有类似的问题也需要约会。这是我的代码:

var disjunction= new Disjunction();

disjunction.Add(Restrictions.On<LocalAsset>(e => e.AvailableFrom).IsBetween(startDate).And(endDate));
disjunction.Add(Restrictions.On<LocalAsset>(e => e.AvailableTo).IsBetween(startDate).And(endDate));

query.Where(disjunction);

答案 2 :(得分:0)

我提出了这个解决方案(不幸的是我没有设法摆脱魔法字符串)

protected Disjunction GetChangedDisjunction<T>(string alias, Disjunction junction = null) where T : IHaveDate
    {
        if(junction == null)
            junction = new Disjunction();

        var toDatum = DateTime.Now;
        junction.Add(Restrictions.And(
                        Expression.Gt(string.Format("{0}.DeletedDate", alias), fromDate), 
                        Expression.Lt(string.Format("{0}.DeletedDate", alias), toDate)));
        junction.Add(Restrictions.Gt(string.Format("{0}.CreatedDate", alias), fromDate));
        junction.Add(Restrictions.Gt(string.Format("{0}.UpdatedDate", alias), fromDate));

        return junction;
    }

然后我像这样使用它:

User userAlias= null;
var queryOverUser = QueryOver.Of( () => userAlias);

Program programAlias = null;
queryOverUser 
    .JoinQueryOver(a => a.Programs, () => programAlias, JoinType.LeftOuterJoin)

Disjunction disjunction = new Disjunction();
GetChangedDisjunction<User>("userAlias", disjunction);
GetChangedDisjunction<Program>("programAlias", disjunction);

queryOverUser.Where(disjunction);