NHibernate - 创建自定义 Linq 扩展时出现问题

问题描述 投票:0回答:1

我在 NH Linq 有这样的查询:

var query = _session
    .Query<Revision>()
    .Join(
        _session.Query<Document>(),
        rev => rev.Document,
        doc => doc,
        (rev, doc) => new FolderDocumentRevision { Revision = rev, Document = doc }
    ).Where(
        item => item.Document.OrganisationalUnitRights.Any(cr => (cr.OrganisationalUnit!=null && parentOus.Contains(cr.OrganisationalUnit.Id) ||
                cr.RoleId!=null && (_securityInfo.SessionData.Profile.SystemRoleId==cr.RoleId || _securityInfo.SessionData.Profile.ApplicationRoleId==cr.RoleId )) 
            && cr.CanView)

    );

我正在尝试创建一个扩展以在Where部分中使用HasAccess方法。

query = query.Where(
    item => item.Document.OrganisationalUnitRights.HasAccess(SessionFactory,_securityInfo,cr => cr.CanView)
);

花了几个小时,我还是没能完成这个。我遇到的最多问题是转换 Any() 和parentOus.Contains。这是我的出发点:

public class WithRightLinqGenerator : BaseHqlGeneratorForMethod
{
    public WithRightLinqGenerator()
    {
        SupportedMethods = new[]
        {
            NHibernate.Util.ReflectHelper.GetMethodDefinition<ICollection<OrganisationalUnitRight>>(rights => rights.HasAccess(null, null, null))
        };
    }

    public override HqlTreeNode BuildHql(
        MethodInfo method,
        Expression targetObject,
        ReadOnlyCollection<Expression> arguments,
        HqlTreeBuilder treeBuilder,
        IHqlExpressionVisitor visitor)
    {
        var rightsExpression = visitor.Visit(arguments[0]).AsExpression();//visitor.Visit(targetObject).AsExpression();

        // The second argument is SessionContainer
        var sessionContainerExpression = arguments[1];
        var sessionContainerValue = GetConstantValue(sessionContainerExpression) as SessionContainer;

        // The third argument is SecurityInfo
        var securityInfoExpression = arguments[2];
        var securityInfoValue = GetConstantValue(securityInfoExpression) as SecurityInfo;

        var parentOus = sessionContainerValue.OUHierarchy.GetAllParents(securityInfoValue.SessionData.Profile.Id).ToList();
        var systemRoleId = securityInfoValue.SessionData.Profile.SystemRoleId;
        var applicationRoleId = securityInfoValue.SessionData.Profile.ApplicationRoleId;

        
    }
    private object GetConstantValue(Expression expression)
    {
        if (expression is ConstantExpression constantExpression)
        {
            return constantExpression.Value;
        }

        // You can extend this method to handle other types of expressions if needed
        throw new InvalidOperationException("Expected a constant expression.");
    }
}

如何转换此查询?

linq nhibernate hql expression-trees linq-to-nhibernate
1个回答
0
投票

根据@Svyatoslav Danyliv 的评论,有一种更简单的方法可以解决这个问题。您需要使用 LINQKit 库。然后我创建了两个方法:

    [Expandable(nameof(HasAccess))]
    public static bool HasAccess(
        this ICollection<OrganisationalUnitRight> rights,
        SessionContainer sessionFactory,
        SecurityInfo securityInfo,
        Func<OrganisationalUnitRight, bool> rightSelector
    )
    {
        throw new NotImplementedException();
    }
    
    private static Expression<Func<ICollection<OrganisationalUnitRight>,SessionContainer,SecurityInfo,Func<OrganisationalUnitRight, bool> , bool>> HasAccess()
        => (rights,sessionFactory,securityInfo,rightSelector) => rights.Any(
            cr =>
            (
                sessionFactory.OUHierarchy.GetAllParents(securityInfo.SessionData.Profile.Id).Contains(cr.OrganisationalUnit.Id)
                || (
                    cr.RoleId.HasValue
                    && (
                        securityInfo.SessionData.Profile.SystemRoleId == cr.RoleId
                        || securityInfo.SessionData.Profile.ApplicationRoleId == cr.RoleId
                    )
                ) && rightSelector(cr)
            ));

注意,该方法具有 ExpandableAttribute 属性。

现在,当我想在 NH Linq 查询中使用它时,我需要首先调用 AsExpandable() 方法:

query = query.AsExpandable().Where(
        item => item.Document.OrganisationalUnitRights.HasAccess(SessionFactory,_securityInfo,cr => cr.CanView)

);

© www.soinside.com 2019 - 2024. All rights reserved.