4

ヒューストンには問題があります...いや、私だけだと思います。:)

NHibernate QueryOver オブジェクトでサブクエリを実行しようとしています。サブクエリのないクエリは正常に機能しますが、サブクエリが追加されるとすべてが崩壊します。

EDIT1:
私が達成したいのは、コンテナへのすべての関係で AccountStatus プロパティが DELETED に設定されているすべてのユーザーを選択することです

var queryOver = session.QueryOver<User>();

queryOver.WhereRestrictionOn(x => x.UserHasContainer).IsNotEmpty
         .JoinQueryOver<ContainerUser>(x => x.UserHasContainer)
         .WithSubquery.WhereAll(x => x.AccountStatus == AccountStatus.DELETED);

この例外が発生し続けます:

System.Exception: right operand should be detachedQueryInstance.As<T>() - "DELETED"
at NHibernate.Impl.ExpressionProcessor.FindDetachedCriteria(Expression expression)
at NHibernate.Impl.ExpressionProcessor.ProcessSubqueryExpression(LambdaSubqueryType subqueryType, BinaryExpression be)
at NHibernate.Impl.ExpressionProcessor.ProcessSubquery[T](LambdaSubqueryType subqueryType, Expression`1 expression)
at NHibernate.Criterion.Subqueries.WhereAll[T](Expression`1 expression)
at RBAC.Infrastructure.DataAccess.QueryObject.Implementation.UserQueryObject.FilterByContainerRelationsAreScheduledForDeletion(IQueryOver`2 queryOver) in c:\APPL\dev\RBAC\Dev\RBAC.Infrastructure\DataAccess\QueryObject\Implementation\UserQueryObject.cs:line 113
at RBAC.Infrastructure.DataAccess.QueryObject.Implementation.UserQueryObject._ExecuteQuery(IQueryOver`2 queryOver) in c:\APPL\dev\RBAC\Dev\RBAC.Infrastructure\DataAccess\QueryObject\Implementation\UserQueryObject.cs:line 101
at RBAC.Infrastructure.DataAccess.QueryObject.Base.BaseQueryObject`1.ExecuteQuery(ISessionDecorater session) in c:\APPL\dev\RBAC\Dev\RBAC.Infrastructure\DataAccess\QueryObject\Base\BaseQueryObject.cs:line 20
at RBAC.Infrastructure.DataAccess.GenericDAO.Implementation.GenericDAO.GetByQueryObject[T](IQueryObject`1 queryObject) in c:\APPL\dev\RBAC\Dev\RBAC.Infrastructure\DataAccess\GenericDAO\Implementation\GenericDAO.cs:line 253
at RBAC.Infrastructure.BusinessService.CleanupModule.Implementation.RBACCleanerActions.CleanUpUsers() in c:\APPL\dev\RBAC\Dev\RBAC.Infrastructure\BusinessService\CleanupModule\Implementation\RBACCleanerActions.cs:line 59

右のオペランドが detachedQueryInstanceである必要があり、他のクエリも運が悪いため、上下左右にグーグルで検索しました。ここの誰かが何が間違っているのか、そして将来これらの問題を解決する方法を知っていることを願っています.

私もこのクエリを試してみましたが、うまくいきませんでした:

queryOver.WhereRestrictionOn(x => x.UserHasContainer).IsNotEmpty
         .JoinQueryOver<ContainerUser>(x => x.UserHasContainer)
         .Where(Subqueries.WhereAll<ContainerUser>(x => x.AccountStatus == AccountStatus.DELETED));

例外:

System.InvalidCastException: Unable to cast object of type 'System.Linq.Expressions.PropertyExpression' to type 'System.Linq.Expressions.BinaryExpression'.
at NHibernate.Impl.ExpressionProcessor.ProcessSubquery[T](LambdaSubqueryType subqueryType, Expression`1 expression)
at NHibernate.Criterion.Subqueries.WhereAll[T](Expression`1 expression)
at RBAC.Infrastructure.DataAccess.QueryObject.Implementation.UserQueryObject.FilterByUsersWereAllTheirFunctionRelationsAreScheduledForDeletion(IQueryOver`2 queryOver) in c:\APPL\dev\RBAC\Dev\RBAC.Infrastructure\DataAccess\QueryObject\Implementation\UserQueryObject.cs:line 157
at RBAC.Infrastructure.DataAccess.QueryObject.Implementation.UserQueryObject._ExecuteQuery(IQueryOver`2 queryOver) in c:\APPL\dev\RBAC\Dev\RBAC.Infrastructure\DataAccess\QueryObject\Implementation\UserQueryObject.cs:line 97
at RBAC.Infrastructure.DataAccess.QueryObject.Base.BaseQueryObject`1.ExecuteQuery(ISessionDecorater session) in c:\APPL\dev\RBAC\Dev\RBAC.Infrastructure\DataAccess\QueryObject\Base\BaseQueryObject.cs:line 21
at RBAC.Infrastructure.DataAccess.GenericDAO.Implementation.GenericDAO.GetByQueryObject[T](IQueryObject`1 queryObject) in c:\APPL\dev\RBAC\Dev\RBAC.Infrastructure\DataAccess\GenericDAO\Implementation\GenericDAO.cs:line 253
at RBAC.Infrastructure.BusinessService.ADModule.Implementation.DeletionFlagSetter.FlagUsersForDeletionWereAllRelationsAreFlaggedForDeletionForADRegisteredUsers() in c:\APPL\dev\RBAC\Dev\RBAC.Infrastructure\BusinessService\ADModule\Implementation\DeletionFlagSetter.cs:line 115
at RBAC.Infrastructure.BusinessService.ADModule.Implementation.ActiveDirectorySynchronizer.Synchronize() in c:\APPL\dev\RBAC\Dev\RBAC.Infrastructure\BusinessService\ADModule\Implementation\ActiveDirectorySynchronizer.cs:line 156

EDIT2:
ユーザーのリストがあれば、linqで同等のものはこれになると思います。

users.Where(x => x.UserHasFunctions.All(y => y.IsDeleted)).ToList();
4

1 に答える 1

5

私が QueryOver クエリを処理しようとするときに通常行う最初のステップは、正しい SQL を考え出すことです。LINQ クエリに基づいて、次のようになると思います。

select
    User.*
from
    User
where
    /* Or whatever "deleted" turns out to be, not necessarily '1' */
    1 = all (select AccountStatus          
             from ContainerUser
             where ContainerUser.UserId = User.Id);

基本的に、そのユーザーのすべてのContainerUser行がAccountStatus削除されているすべてのユーザーを取得します。

したがって、QueryOver では次のように記述できます。

User userAlias = null;

session.QueryOver<User>(() => userAlias)
    .WithSubquery.WhereValue(AccountStatus.DELETED).EqAll(QueryOver.Of<ContainerUser>()
        .Where(uc => uc.User.Id == userAlias.Id)
        .Select(uc => uc.AccountStatus));

// select list, more restrictions, etc.
于 2013-06-27T12:48:27.423 に答える