From ecc761a232d7ba2f2d75c3d61ca3090b3889a794 Mon Sep 17 00:00:00 2001 From: Shannon Date: Thu, 31 Aug 2017 22:19:01 +1000 Subject: [PATCH] Change EntityService GetDescendents to lookup the item path to use in the LIKE query to be a 'prefix' query not a 'contains' query which will be much better for SQL --- src/Umbraco.Core/Services/EntityService.cs | 47 ++++++++++++++++++--- src/Umbraco.Core/Services/IEntityService.cs | 7 +++ 2 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Core/Services/EntityService.cs b/src/Umbraco.Core/Services/EntityService.cs index 6e4b5ef17c..de7274433b 100644 --- a/src/Umbraco.Core/Services/EntityService.cs +++ b/src/Umbraco.Core/Services/EntityService.cs @@ -349,10 +349,20 @@ namespace Umbraco.Core.Services { var repository = RepositoryFactory.CreateEntityRepository(uow); + //lookup the path so we can use it in the prefix query below + var itemPath = repository.GetAllPaths(objectTypeId, id).ToArray(); + if (itemPath.Length == 0) + { + totalRecords = 0; + return Enumerable.Empty(); + } + var query = Query.Builder; //if the id is System Root, then just get all if (id != Constants.System.Root) - query.Where(x => x.Path.SqlContains(string.Format(",{0},", id), TextColumnType.NVarchar)); + { + query.Where(x => x.Path.SqlStartsWith(string.Format("{0},", itemPath[0].Path), TextColumnType.NVarchar)); + } IQuery filterQuery = null; if (filter.IsNullOrWhiteSpace() == false) @@ -381,15 +391,25 @@ namespace Umbraco.Core.Services using (var uow = UowProvider.GetUnitOfWork(readOnly: true)) { var repository = RepositoryFactory.CreateEntityRepository(uow); - + var query = Query.Builder; if (idsA.All(x => x != Constants.System.Root)) { + //lookup the paths so we can use it in the prefix query below + var itemPaths = repository.GetAllPaths(objectTypeId, idsA).ToArray(); + if (itemPaths.Length == 0) + { + totalRecords = 0; + return Enumerable.Empty(); + } + var clauses = new List>>(); foreach (var id in idsA) { + var path = itemPaths.FirstOrDefault(x => x.Id == id); + if (path == null) continue; var qid = id; - clauses.Add(x => x.Path.SqlContains(string.Format(",{0},", qid), TextColumnType.NVarchar) || x.Path.SqlEndsWith(string.Format(",{0}", qid), TextColumnType.NVarchar)); + clauses.Add(x => x.Path.SqlStartsWith(string.Format("{0},", path), TextColumnType.NVarchar) || x.Path.SqlEndsWith(string.Format(",{0}", qid), TextColumnType.NVarchar)); } query.WhereAny(clauses); } @@ -443,6 +463,21 @@ namespace Umbraco.Core.Services } } + /// + public virtual IEnumerable GetAncestors(int id) + { + using (var uow = UowProvider.GetUnitOfWork(readOnly: true)) + { + var repository = RepositoryFactory.CreateEntityRepository(uow); + var entity = repository.Get(id); + var pathMatch = entity.Path + ","; + var query = Query.Builder.Where(x => x.Path.StartsWith(pathMatch) && x.Id != id); + + var entities = repository.GetByQuery(query); + return entities; + } + } + /// /// Gets a collection of descendents by the parents Id /// @@ -601,13 +636,13 @@ namespace Umbraco.Core.Services return repository.GetAllPaths(objectTypeId, keys); } } - + /// - /// Gets a collection of + /// Gets a collection of /// /// Guid id of the UmbracoObjectType /// - /// An enumerable list of objects + /// An enumerable list of objects public virtual IEnumerable GetAll(Guid objectTypeId, params int[] ids) { var umbracoObjectType = UmbracoObjectTypesExtensions.GetUmbracoObjectType(objectTypeId); diff --git a/src/Umbraco.Core/Services/IEntityService.cs b/src/Umbraco.Core/Services/IEntityService.cs index 3136a49bf3..21bd8a3c6e 100644 --- a/src/Umbraco.Core/Services/IEntityService.cs +++ b/src/Umbraco.Core/Services/IEntityService.cs @@ -203,6 +203,13 @@ namespace Umbraco.Core.Services /// An enumerable list of objects IEnumerable GetDescendents(int id); + /// + /// Gets a collection of ancestors by the parents Id + /// + /// Id of entity to retrieve ancestors for + /// An enumerable list of objects + IEnumerable GetAncestors(int id); + /// /// Gets a collection of descendents by the parents Id ///