如何在这里摆脱交叉连接?
How to get rid of cross join here?
我有执行缓慢的代码,因为被转换成奇怪的 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 JOINs,但是 SecureActions 和 Users 只是 CROSS JOINed (?!)
我很惊讶,因为从条件来看,应该只选择了一个用户,例如,所以我预计会是这样的:
INNER JOIN "XXX"."USER" "ExtentY" ON ("ExtentY"."USER_NAME" = :p__linq__Z)
而不是
CROSS JOIN "XXX"."USER"
你能告诉我,这里有什么问题吗?
匿名对象救了我(然而,性能仍然不佳,但这已经是数据库管理员的问题,因为他们说 Oracle 计划不是最优的):
// Select objects from supplied queryable
from secureObject in source
// Get user matching current principal id
join u in this.Users on new { key = userName } equals new { key = u.Name }
// Get action entry for supplied action
join ac in this.SecureActions on new { key1 = actionType, key2 = true } equals new { key1 = ac.Type, key2 = ac.AppliesToObject }
我有执行缓慢的代码,因为被转换成奇怪的 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 JOINs,但是 SecureActions 和 Users 只是 CROSS JOINed (?!)
我很惊讶,因为从条件来看,应该只选择了一个用户,例如,所以我预计会是这样的:
INNER JOIN "XXX"."USER" "ExtentY" ON ("ExtentY"."USER_NAME" = :p__linq__Z)
而不是
CROSS JOIN "XXX"."USER"
你能告诉我,这里有什么问题吗?
匿名对象救了我(然而,性能仍然不佳,但这已经是数据库管理员的问题,因为他们说 Oracle 计划不是最优的):
// Select objects from supplied queryable
from secureObject in source
// Get user matching current principal id
join u in this.Users on new { key = userName } equals new { key = u.Name }
// Get action entry for supplied action
join ac in this.SecureActions on new { key1 = actionType, key2 = true } equals new { key1 = ac.Type, key2 = ac.AppliesToObject }