From f7d7a43720f5b92c072473abd0c044ae0a9d88fe Mon Sep 17 00:00:00 2001 From: Shannon Date: Wed, 25 Jan 2017 15:15:28 +1100 Subject: [PATCH] Fixes BulkInsertRecords to not require a trans , removes inner trans from PermissionRepository, fixes up events in PermissionRepository and MemberGroupRepository, fixes up uow in UserService --- .../Persistence/PetaPocoExtensions.cs | 31 +++- .../Repositories/MemberGroupRepository.cs | 2 +- .../Repositories/PermissionRepository.cs | 155 ++++++++---------- src/Umbraco.Core/Services/ContentService.cs | 6 +- src/Umbraco.Core/Services/UserService.cs | 87 ++++++---- 5 files changed, 156 insertions(+), 125 deletions(-) diff --git a/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs b/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs index 22e66935bf..abe61ef45a 100644 --- a/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs +++ b/src/Umbraco.Core/Persistence/PetaPocoExtensions.cs @@ -183,16 +183,31 @@ namespace Umbraco.Core.Persistence /// /// /// + [Obsolete("Use the method that specifies an SqlSyntaxContext instance instead")] public static void BulkInsertRecords(this Database db, IEnumerable collection) { - //don't do anything if there are no records. - if (collection.Any() == false) - return; + db.BulkInsertRecords(collection, null, SqlSyntaxContext.SqlSyntaxProvider, true, false); + } - using (var tr = db.GetTransaction()) - { - db.BulkInsertRecords(collection, tr, SqlSyntaxContext.SqlSyntaxProvider, true, true); // use native, commit - } + + /// + /// Performs the bulk insertion + /// + /// + /// + /// + /// + /// + /// If this is false this will try to just generate bulk insert statements instead of using the current SQL platform's bulk + /// insert logic. For SQLCE, bulk insert statements do not work so if this is false it will insert one at a time. + /// + /// The number of items inserted + public static int BulkInsertRecords(this Database db, + IEnumerable collection, + ISqlSyntaxProvider syntaxProvider, + bool useNativeSqlPlatformBulkInsert = true) + { + return BulkInsertRecords(db, collection, null, syntaxProvider, useNativeSqlPlatformBulkInsert, false); } /// @@ -267,6 +282,7 @@ namespace Umbraco.Core.Persistence if (commitTrans) { + if (tr == null) throw new ArgumentNullException("The transaction cannot be null if commitTrans is true"); tr.Complete(); } return processed; @@ -275,6 +291,7 @@ namespace Umbraco.Core.Persistence { if (commitTrans) { + if (tr == null) throw new ArgumentNullException("The transaction cannot be null if commitTrans is true"); tr.Dispose(); } throw; diff --git a/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs b/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs index 83676ae881..313b3c703a 100644 --- a/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/MemberGroupRepository.cs @@ -276,7 +276,7 @@ namespace Umbraco.Core.Persistence.Repositories { PersistNewItem(m); } - SavedMemberGroup.RaiseEvent(new SaveEventArgs(missingGroups), this); + SavedMemberGroup.RaiseEvent(new SaveEventArgs(missingGroups), this, UnitOfWork.EventManager); //now go get all the dto's for roles with these role names var rolesForNames = Database.Fetch(existingSql).ToArray(); diff --git a/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs b/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs index aa671dccec..51da53ca90 100644 --- a/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/PermissionRepository.cs @@ -25,11 +25,11 @@ namespace Umbraco.Core.Persistence.Repositories internal class PermissionRepository where TEntity : class, IAggregateRoot { - private readonly IDatabaseUnitOfWork _unitOfWork; + private readonly IScopeUnitOfWork _unitOfWork; private readonly IRuntimeCacheProvider _runtimeCache; private readonly ISqlSyntaxProvider _sqlSyntax; - internal PermissionRepository(IDatabaseUnitOfWork unitOfWork, CacheHelper cache, ISqlSyntaxProvider sqlSyntax) + internal PermissionRepository(IScopeUnitOfWork unitOfWork, CacheHelper cache, ISqlSyntaxProvider sqlSyntax) { _unitOfWork = unitOfWork; //Make this repository use an isolated cache @@ -126,37 +126,33 @@ namespace Umbraco.Core.Persistence.Repositories public void ReplaceUserPermissions(int userId, IEnumerable permissions, params int[] entityIds) { var db = _unitOfWork.Database; - using (var trans = db.GetTransaction()) + + //we need to batch these in groups of 2000 so we don't exceed the max 2100 limit + foreach (var idGroup in entityIds.InGroupsOf(2000)) { - //we need to batch these in groups of 2000 so we don't exceed the max 2100 limit - foreach (var idGroup in entityIds.InGroupsOf(2000)) - { - db.Execute("DELETE FROM umbracoUser2NodePermission WHERE userId=@userId AND nodeId in (@nodeIds)", - new { userId = userId, nodeIds = idGroup }); - } - - var toInsert = new List(); - foreach (var p in permissions) - { - foreach (var e in entityIds) - { - toInsert.Add(new User2NodePermissionDto - { - NodeId = e, - Permission = p.ToString(CultureInfo.InvariantCulture), - UserId = userId - }); - } - } - - _unitOfWork.Database.BulkInsertRecords(toInsert, trans); - - trans.Complete(); - - //Raise the event - AssignedPermissions.RaiseEvent( - new SaveEventArgs(ConvertToPermissionList(toInsert), false), this); + db.Execute("DELETE FROM umbracoUser2NodePermission WHERE userId=@userId AND nodeId in (@nodeIds)", + new { userId = userId, nodeIds = idGroup }); } + + var toInsert = new List(); + foreach (var p in permissions) + { + foreach (var e in entityIds) + { + toInsert.Add(new User2NodePermissionDto + { + NodeId = e, + Permission = p.ToString(CultureInfo.InvariantCulture), + UserId = userId + }); + } + } + + _unitOfWork.Database.BulkInsertRecords(toInsert, _sqlSyntax); + + //Raise the event + AssignedPermissions.RaiseEvent( + new SaveEventArgs(ConvertToPermissionList(toInsert), false), this, _unitOfWork.EventManager); } /// @@ -168,31 +164,26 @@ namespace Umbraco.Core.Persistence.Repositories public void AssignUserPermission(int userId, char permission, params int[] entityIds) { var db = _unitOfWork.Database; - using (var trans = db.GetTransaction()) - { - db.Execute("DELETE FROM umbracoUser2NodePermission WHERE userId=@userId AND permission=@permission AND nodeId in (@entityIds)", - new - { - userId = userId, - permission = permission.ToString(CultureInfo.InvariantCulture), - entityIds = entityIds - }); - - var actions = entityIds.Select(id => new User2NodePermissionDto + db.Execute("DELETE FROM umbracoUser2NodePermission WHERE userId=@userId AND permission=@permission AND nodeId in (@entityIds)", + new { - NodeId = id, - Permission = permission.ToString(CultureInfo.InvariantCulture), - UserId = userId - }).ToArray(); + userId = userId, + permission = permission.ToString(CultureInfo.InvariantCulture), + entityIds = entityIds + }); - _unitOfWork.Database.BulkInsertRecords(actions, trans); + var actions = entityIds.Select(id => new User2NodePermissionDto + { + NodeId = id, + Permission = permission.ToString(CultureInfo.InvariantCulture), + UserId = userId + }).ToArray(); - trans.Complete(); - - //Raise the event - AssignedPermissions.RaiseEvent( - new SaveEventArgs(ConvertToPermissionList(actions), false), this); - } + _unitOfWork.Database.BulkInsertRecords(actions, _sqlSyntax); + + //Raise the event + AssignedPermissions.RaiseEvent( + new SaveEventArgs(ConvertToPermissionList(actions), false), this, _unitOfWork.EventManager); } /// @@ -204,31 +195,26 @@ namespace Umbraco.Core.Persistence.Repositories public void AssignEntityPermission(TEntity entity, char permission, IEnumerable userIds) { var db = _unitOfWork.Database; - using (var trans = db.GetTransaction()) - { - db.Execute("DELETE FROM umbracoUser2NodePermission WHERE nodeId=@nodeId AND permission=@permission AND userId in (@userIds)", + db.Execute("DELETE FROM umbracoUser2NodePermission WHERE nodeId=@nodeId AND permission=@permission AND userId in (@userIds)", new { - nodeId = entity.Id, + nodeId = entity.Id, permission = permission.ToString(CultureInfo.InvariantCulture), userIds = userIds }); - var actions = userIds.Select(id => new User2NodePermissionDto - { - NodeId = entity.Id, - Permission = permission.ToString(CultureInfo.InvariantCulture), - UserId = id - }).ToArray(); + var actions = userIds.Select(id => new User2NodePermissionDto + { + NodeId = entity.Id, + Permission = permission.ToString(CultureInfo.InvariantCulture), + UserId = id + }).ToArray(); - _unitOfWork.Database.BulkInsertRecords(actions, trans); + _unitOfWork.Database.BulkInsertRecords(actions, _sqlSyntax); - trans.Complete(); - - //Raise the event - AssignedPermissions.RaiseEvent( - new SaveEventArgs(ConvertToPermissionList(actions), false), this); - } + //Raise the event + AssignedPermissions.RaiseEvent( + new SaveEventArgs(ConvertToPermissionList(actions), false), this, _unitOfWork.EventManager); } /// @@ -242,25 +228,20 @@ namespace Umbraco.Core.Persistence.Repositories public void ReplaceEntityPermissions(EntityPermissionSet permissionSet) { var db = _unitOfWork.Database; - using (var trans = db.GetTransaction()) + db.Execute("DELETE FROM umbracoUser2NodePermission WHERE nodeId=@nodeId", new { nodeId = permissionSet.EntityId }); + + var actions = permissionSet.UserPermissionsSet.Select(p => new User2NodePermissionDto { - db.Execute("DELETE FROM umbracoUser2NodePermission WHERE nodeId=@nodeId", new { nodeId = permissionSet.EntityId }); + NodeId = permissionSet.EntityId, + Permission = p.Permission, + UserId = p.UserId + }).ToArray(); - var actions = permissionSet.UserPermissionsSet.Select(p => new User2NodePermissionDto - { - NodeId = permissionSet.EntityId, - Permission = p.Permission, - UserId = p.UserId - }).ToArray(); - - _unitOfWork.Database.BulkInsertRecords(actions, trans); - - trans.Complete(); - - //Raise the event - AssignedPermissions.RaiseEvent( - new SaveEventArgs(ConvertToPermissionList(actions), false), this); - } + _unitOfWork.Database.BulkInsertRecords(actions, _sqlSyntax); + + //Raise the event + AssignedPermissions.RaiseEvent( + new SaveEventArgs(ConvertToPermissionList(actions), false), this, _unitOfWork.EventManager); } private static IEnumerable ConvertToPermissionList(IEnumerable result) diff --git a/src/Umbraco.Core/Services/ContentService.cs b/src/Umbraco.Core/Services/ContentService.cs index acfdce8291..ac128f567d 100644 --- a/src/Umbraco.Core/Services/ContentService.cs +++ b/src/Umbraco.Core/Services/ContentService.cs @@ -107,10 +107,11 @@ namespace Umbraco.Core.Services /// public void ReplaceContentPermissions(EntityPermissionSet permissionSet) { - var uow = UowProvider.GetReadOnlyUnitOfWork(); + var uow = UowProvider.GetUnitOfWork(); using (var repository = RepositoryFactory.CreateContentRepository(uow)) { repository.ReplaceContentPermissions(permissionSet); + uow.Commit(); } } @@ -122,10 +123,11 @@ namespace Umbraco.Core.Services /// public void AssignContentPermission(IContent entity, char permission, IEnumerable userIds) { - var uow = UowProvider.GetReadOnlyUnitOfWork(); + var uow = UowProvider.GetUnitOfWork(); using (var repository = RepositoryFactory.CreateContentRepository(uow)) { repository.AssignEntityPermission(entity, permission, userIds); + uow.Commit(); } } diff --git a/src/Umbraco.Core/Services/UserService.cs b/src/Umbraco.Core/Services/UserService.cs index f4f05c6861..a0945e3623 100644 --- a/src/Umbraco.Core/Services/UserService.cs +++ b/src/Umbraco.Core/Services/UserService.cs @@ -42,7 +42,7 @@ namespace Umbraco.Core.Services /// Alias of the default MemberType public string GetDefaultMemberType() { - using (var repository = RepositoryFactory.CreateUserTypeRepository(UowProvider.GetUnitOfWork())) + using (var repository = RepositoryFactory.CreateUserTypeRepository(UowProvider.GetReadOnlyUnitOfWork())) { var types = repository.GetAll().Select(x => x.Alias).ToArray(); @@ -73,7 +73,7 @@ namespace Umbraco.Core.Services /// True if the User exists otherwise False public bool Exists(string username) { - using (var repository = RepositoryFactory.CreateUserRepository(UowProvider.GetUnitOfWork())) + using (var repository = RepositoryFactory.CreateUserRepository(UowProvider.GetReadOnlyUnitOfWork())) { return repository.Exists(username); } @@ -152,12 +152,15 @@ namespace Umbraco.Core.Services user.AddAllowedSection("media"); if (SavingUser.IsRaisedEventCancelled(new SaveEventArgs(user), this, uow.EventManager)) + { + uow.Commit(); return user; + } repository.AddOrUpdate(user); uow.Commit(); - SavedUser.RaiseEvent(new SaveEventArgs(user, false), this); + SavedUser.RaiseEvent(new SaveEventArgs(user, false), this ,uow.EventManager); return user; } @@ -170,7 +173,7 @@ namespace Umbraco.Core.Services /// public IUser GetById(int id) { - using (var repository = RepositoryFactory.CreateUserRepository(UowProvider.GetUnitOfWork())) + using (var repository = RepositoryFactory.CreateUserRepository(UowProvider.GetReadOnlyUnitOfWork())) { var user = repository.Get((int)id); @@ -201,7 +204,7 @@ namespace Umbraco.Core.Services /// public IUser GetByEmail(string email) { - using (var repository = RepositoryFactory.CreateUserRepository(UowProvider.GetUnitOfWork())) + using (var repository = RepositoryFactory.CreateUserRepository(UowProvider.GetReadOnlyUnitOfWork())) { var query = Query.Builder.Where(x => x.Email.Equals(email)); var user = repository.GetByQuery(query).FirstOrDefault(); @@ -217,7 +220,7 @@ namespace Umbraco.Core.Services /// public IUser GetByUsername(string username) { - using (var repository = RepositoryFactory.CreateUserRepository(UowProvider.GetUnitOfWork())) + using (var repository = RepositoryFactory.CreateUserRepository(UowProvider.GetReadOnlyUnitOfWork())) { var query = Query.Builder.Where(x => x.Username.Equals(username)); var user = repository.GetByQuery(query).FirstOrDefault(); @@ -288,12 +291,16 @@ namespace Umbraco.Core.Services using (var repository = RepositoryFactory.CreateUserRepository(uow)) { if (DeletingUser.IsRaisedEventCancelled(new DeleteEventArgs(user), this, uow.EventManager)) + { + uow.Commit(); return; + } repository.Delete(user); uow.Commit(); + DeletedUser.RaiseEvent(new DeleteEventArgs(user, false), this, uow.EventManager); + } - DeletedUser.RaiseEvent(new DeleteEventArgs(user, false), this); } } @@ -311,12 +318,18 @@ namespace Umbraco.Core.Services if (raiseEvents) { if (SavingUser.IsRaisedEventCancelled(new SaveEventArgs(entity), this, uow.EventManager)) + { + uow.Commit(); return; + } } repository.AddOrUpdate(entity); try { uow.Commit(); + + if (raiseEvents) + SavedUser.RaiseEvent(new SaveEventArgs(entity, false), this, uow.EventManager); } catch (DbException ex) { @@ -328,8 +341,7 @@ namespace Umbraco.Core.Services } } - if (raiseEvents) - SavedUser.RaiseEvent(new SaveEventArgs(entity, false), this); + } /// @@ -340,24 +352,30 @@ namespace Umbraco.Core.Services /// Default is True otherwise set to False to not raise events public void Save(IEnumerable entities, bool raiseEvents = true) { + var asArray = entities.ToArray(); using (var uow = UowProvider.GetUnitOfWork()) using (var repository = RepositoryFactory.CreateUserRepository(uow)) { if (raiseEvents) { - if (SavingUser.IsRaisedEventCancelled(new SaveEventArgs(entities), this, uow.EventManager)) + if (SavingUser.IsRaisedEventCancelled(new SaveEventArgs(asArray), this, uow.EventManager)) + { + uow.Commit(); return; + } } - foreach (var member in entities) + foreach (var member in asArray) { repository.AddOrUpdate(member); } //commit the whole lot in one go uow.Commit(); + + if (raiseEvents) + SavedUser.RaiseEvent(new SaveEventArgs(asArray, false), this, uow.EventManager); } - if (raiseEvents) - SavedUser.RaiseEvent(new SaveEventArgs(entities, false), this); + } /// @@ -371,7 +389,7 @@ namespace Umbraco.Core.Services /// public IEnumerable FindByEmail(string emailStringToMatch, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith) { - var uow = UowProvider.GetUnitOfWork(); + var uow = UowProvider.GetReadOnlyUnitOfWork(); using (var repository = RepositoryFactory.CreateUserRepository(uow)) { var query = new Query(); @@ -412,7 +430,7 @@ namespace Umbraco.Core.Services /// public IEnumerable FindByUsername(string login, int pageIndex, int pageSize, out int totalRecords, StringPropertyMatchType matchType = StringPropertyMatchType.StartsWith) { - var uow = UowProvider.GetUnitOfWork(); + var uow = UowProvider.GetReadOnlyUnitOfWork(); using (var repository = RepositoryFactory.CreateUserRepository(uow)) { var query = new Query(); @@ -454,7 +472,7 @@ namespace Umbraco.Core.Services /// with number of Users for passed in type public int GetCount(MemberCountType countType) { - using (var repository = RepositoryFactory.CreateUserRepository(UowProvider.GetUnitOfWork())) + using (var repository = RepositoryFactory.CreateUserRepository(UowProvider.GetReadOnlyUnitOfWork())) { IQuery query; @@ -497,7 +515,7 @@ namespace Umbraco.Core.Services /// public IEnumerable GetAll(int pageIndex, int pageSize, out int totalRecords) { - var uow = UowProvider.GetUnitOfWork(); + var uow = UowProvider.GetReadOnlyUnitOfWork(); using (var repository = RepositoryFactory.CreateUserRepository(uow)) { return repository.GetPagedResultsByQuery(null, pageIndex, pageSize, out totalRecords, member => member.Username); @@ -506,7 +524,7 @@ namespace Umbraco.Core.Services internal IEnumerable GetNextUsers(int id, int count) { - var uow = UowProvider.GetUnitOfWork(); + var uow = UowProvider.GetReadOnlyUnitOfWork(); using (var repository = (UserRepository) RepositoryFactory.CreateUserRepository(uow)) { return repository.GetNextUsers(id, count); @@ -546,7 +564,7 @@ namespace Umbraco.Core.Services /// public IUser GetUserById(int id) { - using (var repository = RepositoryFactory.CreateUserRepository(UowProvider.GetUnitOfWork())) + using (var repository = RepositoryFactory.CreateUserRepository(UowProvider.GetReadOnlyUnitOfWork())) { return repository.Get(id); } @@ -565,6 +583,7 @@ namespace Umbraco.Core.Services using (var repository = RepositoryFactory.CreateUserRepository(uow)) { repository.ReplaceUserPermissions(userId, permissions, entityIds); + uow.Commit(); } } @@ -580,6 +599,8 @@ namespace Umbraco.Core.Services using (var repository = RepositoryFactory.CreateUserRepository(uow)) { repository.AssignUserPermission(userId, permission, entityIds); + uow.Commit(); + } } @@ -590,7 +611,7 @@ namespace Umbraco.Core.Services /// An enumerable list of public IEnumerable GetAllUserTypes(params int[] ids) { - var uow = UowProvider.GetUnitOfWork(); + var uow = UowProvider.GetReadOnlyUnitOfWork(); using (var repository = RepositoryFactory.CreateUserTypeRepository(uow)) { return repository.GetAll(ids); @@ -604,7 +625,7 @@ namespace Umbraco.Core.Services /// public IUserType GetUserTypeByAlias(string alias) { - using (var repository = RepositoryFactory.CreateUserTypeRepository(UowProvider.GetUnitOfWork())) + using (var repository = RepositoryFactory.CreateUserTypeRepository(UowProvider.GetReadOnlyUnitOfWork())) { var query = Query.Builder.Where(x => x.Alias == alias); var contents = repository.GetByQuery(query); @@ -619,7 +640,7 @@ namespace Umbraco.Core.Services /// public IUserType GetUserTypeById(int id) { - using (var repository = RepositoryFactory.CreateUserTypeRepository(UowProvider.GetUnitOfWork())) + using (var repository = RepositoryFactory.CreateUserTypeRepository(UowProvider.GetReadOnlyUnitOfWork())) { return repository.Get(id); } @@ -632,7 +653,7 @@ namespace Umbraco.Core.Services /// public IUserType GetUserTypeByName(string name) { - using (var repository = RepositoryFactory.CreateUserTypeRepository(UowProvider.GetUnitOfWork())) + using (var repository = RepositoryFactory.CreateUserTypeRepository(UowProvider.GetReadOnlyUnitOfWork())) { var query = Query.Builder.Where(x => x.Name == name); var contents = repository.GetByQuery(query); @@ -654,14 +675,18 @@ namespace Umbraco.Core.Services if (raiseEvents) { if (SavingUserType.IsRaisedEventCancelled(new SaveEventArgs(userType), this, uow.EventManager)) + { + uow.Commit(); return; + } } repository.AddOrUpdate(userType); uow.Commit(); + if (raiseEvents) + SavedUserType.RaiseEvent(new SaveEventArgs(userType, false), this, uow.EventManager); } - if (raiseEvents) - SavedUserType.RaiseEvent(new SaveEventArgs(userType, false), this); + } /// @@ -674,12 +699,16 @@ namespace Umbraco.Core.Services using (var repository = RepositoryFactory.CreateUserTypeRepository(uow)) { if (DeletingUserType.IsRaisedEventCancelled(new DeleteEventArgs(userType), this, uow.EventManager)) + { + uow.Commit(); return; + } repository.Delete(userType); uow.Commit(); + DeletedUserType.RaiseEvent(new DeleteEventArgs(userType, false), this, uow.EventManager); + } - DeletedUserType.RaiseEvent(new DeleteEventArgs(userType, false), this); } /// @@ -700,6 +729,7 @@ namespace Umbraco.Core.Services repository.AddOrUpdate(user); } uow.Commit(); + //TODO: Events? } } @@ -723,13 +753,14 @@ namespace Umbraco.Core.Services { users = repository.GetAll(); } - foreach (var user in users.Where(u => !u.AllowedSections.InvariantContains(sectionAlias))) + foreach (var user in users.Where(u => u.AllowedSections.InvariantContains(sectionAlias) == false)) { //now add the section for each user and commit user.AddAllowedSection(sectionAlias); repository.AddOrUpdate(user); } uow.Commit(); + //TODO: Events? } } @@ -742,7 +773,7 @@ namespace Umbraco.Core.Services /// An enumerable list of public IEnumerable GetPermissions(IUser user, params int[] nodeIds) { - var uow = UowProvider.GetUnitOfWork(); + var uow = UowProvider.GetReadOnlyUnitOfWork(); using (var repository = RepositoryFactory.CreateUserRepository(uow)) { var explicitPermissions = repository.GetUserPermissionsForEntities(user.Id, nodeIds);