如何摆脱交叉加入?

时间:2015-09-18 16:33:21

标签: linq-to-sql

我的代码运行缓慢,因为它被转换为奇怪的SQL:

        // Create LINQ query for retrieving objects on which user has permissions to perform supplied action
        var result =

            // Select objects from supplied queryable
            from secureObject in source

            // Create some shorthands for code readablility
            let ownerId = secureObject.AccessControl.OwnerId
            let groupOwner = secureObject.AccessControl.GroupOwner
            let permissions = secureObject.AccessControl.Permissions
            let objectStatus = secureObject.AccessControl.Status

            // Filter out actions that do not apply to this object source
            from ia in this.ImplementedActions
                .Where(ia =>
                    ia.ObjectType == objectType &&
                    ia.ActionType == actionType &&
                    ((ia.Statuses == Status.None) || ((ia.Statuses & objectStatus) != 0))
                )

            // Get action entry for supplied action
            from ac in this.SecureActions.Where(ac => ac.Type == actionType && secureObject != null)

            // Get user matching current principal id
            from u in this.Users.Where(user => user.Name.Equals(userName))

            // Create left outer join for Privileges
            from pr in this.Privileges.Where(pr =>
                pr.ObjectType == objectType
                && pr.Action == actionType
                && (
                    pr.Type == PrivilegeType.Global
                    || (pr.Type == PrivilegeType.Object && pr.RelatedObjectId == secureObject.SecureId)
                    || (pr.Role == RoleType.Self && u.SecureId == secureObject.SecureId && objectType == typeof(User).Name)
                )
            ).DefaultIfEmpty()

            where
                // The action must apply to objects
                ac.AppliesToObject == true
                //ac.AppliesToObject == true

                && (
                // Administrators are always allowed to do everything
                    ((u.Groups & Groups.Administrators) == Groups.Administrators)

                    // Read permissions in the bit field 
                    || (actionType == ActionType.Read && (

                        // The OtherRead access permission bit is on
                        ((permissions & AccessPermissions.OtherRead) != 0)

                        // The OwnerRead access permission bit is on, and the member is the owner
                        || ((permissions & AccessPermissions.OwnerRead) != 0 && ownerId == u.SecureId)

                        // The GroupRead permission bit is on, and the member is in the group
                        || ((permissions & AccessPermissions.GroupRead) != 0 && (groupOwner & u.Groups) != 0))
                    )

                    // Write permissions in the bit field                        
                    || (actionType == ActionType.Write && (

                        // The OtherWrite access permission bit is on
                        ((permissions & AccessPermissions.OtherWrite) != 0)

                        // The OwnerWrite acccess permission bit is on, and the member is the owner
                        || ((permissions & AccessPermissions.OwnerWrite) != 0 && ownerId == u.SecureId)

                        // The GroupWrite permission bit is on, and the member is in the group
                        || ((permissions & AccessPermissions.GroupWrite) != 0 && (groupOwner & u.Groups) != 0))
                    )


                    // Delete permissions in the bit field       
                    || (actionType == ActionType.Delete && (

                        // The OtherDelete access permission bit is on
                        ((permissions & AccessPermissions.OtherDelete) != 0)

                        // The OwnerDelete access permission bit is on, and the member is the owner
                        || ((permissions & AccessPermissions.OwnerDelete) != 0 && ownerId == u.SecureId)

                        // The GroupDelete access permission bit is on, and the member is in the group
                        || ((permissions & AccessPermissions.GroupDelete) != 0 && (groupOwner & u.Groups) != 0))
                    )

                    // User privileges
                    || (pr.Role == RoleType.User && pr.Who == u.SecureId)

                    // Owner privileges
                    || (pr.Role == RoleType.Owner && ownerId == u.SecureId)

                    // OwnerGroups privileges
                    || (pr.Role == RoleType.OwnerGroup && ((groupOwner & u.Groups) != 0))

                    // Group privileges
                    || (pr.Role == RoleType.Group && ((pr.Who & (int)u.Groups) == pr.Who))
                )

                //self privileges
                || (pr.Role == RoleType.Self)

            select secureObject;

这里,ImplementedActions和Privileges相应地转换为INNER / LEFT JOIN,但SecureActions和Users只是CROSS JOINed(?!)

我很惊讶,因为从条件中可以看出,例如,应该只选择一个用户,所以我期待以下内容:

INNER JOIN "XXX"."USER" "ExtentY" ON ("ExtentY"."USER_NAME" = :p__linq__Z)

而不是

CROSS JOIN "XXX"."USER"

你能告诉我这里的问题是什么吗?

1 个答案:

答案 0 :(得分:0)

匿名对象保存了我(但是,性能仍然不好,但它已经成为数据库管理员的一个问题,因为他们说Oracle计划不是最优的):

redirect_to