From 1bc3290497626ebe720806c4af1b62820d12a665 Mon Sep 17 00:00:00 2001 From: Ronald Barendse Date: Wed, 13 Oct 2021 14:10:24 +0200 Subject: [PATCH] Fix bugs in fetching more than 2000 items (permissions and culture variations) --- .../Implement/ContentTypeRepositoryBase.cs | 22 +++++++---- .../Implement/PermissionRepository.cs | 37 +++++++++---------- 2 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs index 8835f8c647..3a74b9209b 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs @@ -1094,14 +1094,20 @@ AND umbracoNode.id <> @id", } } - //lookup all matching rows in umbracoDocumentCultureVariation - var docCultureVariationsToUpdate = editedLanguageVersions.InGroupsOf(Constants.Sql.MaxParameterCount) - .SelectMany(_ => Database.Fetch( - Sql().Select().From() - .WhereIn(x => x.LanguageId, editedLanguageVersions.Keys.Select(x => x.langId).ToList()) - .WhereIn(x => x.NodeId, editedLanguageVersions.Keys.Select(x => x.nodeId)))) - //convert to dictionary with the same key type - .ToDictionary(x => (x.NodeId, (int?)x.LanguageId), x => x); + // lookup all matching rows in umbracoDocumentCultureVariation + // fetch in batches to account for maximum parameter count (distinct languages can't exceed 2000) + var languageIds = editedLanguageVersions.Keys.Select(x => x.langId).Distinct().ToArray(); + var nodeIds = editedLanguageVersions.Keys.Select(x => x.nodeId).Distinct(); + var docCultureVariationsToUpdate = nodeIds.InGroupsOf(Constants.Sql.MaxParameterCount - languageIds.Length) + .SelectMany(group => + { + var sql = Sql().Select().From() + .WhereIn(x => x.LanguageId, languageIds) + .WhereIn(x => x.NodeId, group); + + return Database.Fetch(sql); + }) + .ToDictionary(x => (x.NodeId, (int?)x.LanguageId), x => x); //convert to dictionary with the same key type var toUpdate = new List(); foreach (var ev in editedLanguageVersions) diff --git a/src/Umbraco.Core/Persistence/Repositories/Implement/PermissionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/Implement/PermissionRepository.cs index ce324df685..735496a0d1 100644 --- a/src/Umbraco.Core/Persistence/Repositories/Implement/PermissionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/Implement/PermissionRepository.cs @@ -38,44 +38,41 @@ namespace Umbraco.Core.Persistence.Repositories.Implement /// /// /// - /// This method will not support passing in more than 2000 group Ids + /// This method will not support passing in more than 2000 group IDs when also passing in entity IDs. /// public EntityPermissionCollection GetPermissionsForEntities(int[] groupIds, params int[] entityIds) { var result = new EntityPermissionCollection(); - foreach (var groupOfGroupIds in groupIds.InGroupsOf(Constants.Sql.MaxParameterCount)) + if (entityIds.Length == 0) { - //copy local - var localIds = groupOfGroupIds.ToArray(); - - if (entityIds.Length == 0) + foreach (var group in groupIds.InGroupsOf(Constants.Sql.MaxParameterCount)) { var sql = Sql() .SelectAll() .From() - .Where(dto => localIds.Contains(dto.UserGroupId)); + .Where(dto => group.Contains(dto.UserGroupId)); + var permissions = AmbientScope.Database.Fetch(sql); foreach (var permission in ConvertToPermissionList(permissions)) { result.Add(permission); } } - else + } + else + { + foreach (var group in entityIds.InGroupsOf(Constants.Sql.MaxParameterCount - groupIds.Length)) { - //iterate in groups of 2000 since we don't want to exceed the max SQL param count - foreach (var groupOfEntityIds in entityIds.InGroupsOf(Constants.Sql.MaxParameterCount)) + var sql = Sql() + .SelectAll() + .From() + .Where(dto => groupIds.Contains(dto.UserGroupId) && group.Contains(dto.NodeId)); + + var permissions = AmbientScope.Database.Fetch(sql); + foreach (var permission in ConvertToPermissionList(permissions)) { - var ids = groupOfEntityIds; - var sql = Sql() - .SelectAll() - .From() - .Where(dto => localIds.Contains(dto.UserGroupId) && ids.Contains(dto.NodeId)); - var permissions = AmbientScope.Database.Fetch(sql); - foreach (var permission in ConvertToPermissionList(permissions)) - { - result.Add(permission); - } + result.Add(permission); } } }