diff --git a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs index 846a5e34dd..62b98cf9ad 100644 --- a/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/ContentTypeBaseRepository.cs @@ -764,7 +764,6 @@ AND umbracoNode.id <> @id", out IDictionary> associatedTemplates, out IDictionary> parentContentTypeIds) { - Mandate.That(contentTypeIds.Any(), () => new InvalidOperationException("must be at least one content type id specified")); Mandate.ParameterNotNull(db, "db"); //ensure they are unique @@ -799,8 +798,9 @@ AND umbracoNode.id <> @id", ON Template.nodeId = cmsDocumentType.templateNodeId LEFT JOIN cmsContentType2ContentType as ParentTypes ON ParentTypes.childContentTypeId = cmsContentType.nodeId - WHERE (umbracoNode.nodeObjectType = @nodeObjectType) - AND (umbracoNode.id IN (@contentTypeIds))"; + WHERE (umbracoNode.nodeObjectType = @nodeObjectType)"; + if(contentTypeIds.Any()) + sql = sql + " AND (umbracoNode.id IN (@contentTypeIds))"; //NOTE: we are going to assume there's not going to be more than 2100 content type ids since that is the max SQL param count! if ((contentTypeIds.Length - 1) > 2000) @@ -969,10 +969,12 @@ AND umbracoNode.id <> @id", INNER JOIN cmsDataType as DT ON PT.dataTypeId = DT.[nodeId] LEFT JOIN cmsPropertyTypeGroup as PG - ON PG.[id] = PT.propertyTypeGroupId - WHERE (PT.contentTypeId in (@contentTypeIds)) + ON PG.[id] = PT.propertyTypeGroupId"; - ORDER BY (PG.id)"; + if(contentTypeIds.Any()) + sql = sql + " WHERE (PT.contentTypeId in (@contentTypeIds))"; + + sql = sql + " ORDER BY (PG.id)"; //NOTE: we are going to assume there's not going to be more than 2100 content type ids since that is the max SQL param count! // Since there are 2 groups of params, it will be half! diff --git a/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs index 0e3a6f88d5..3d12cafc1f 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs @@ -14,29 +14,29 @@ namespace Umbraco.Core.Persistence.Repositories /// /// Type of entity for which the repository is used /// Type of the Id used for this entity - internal abstract class RepositoryBase : DisposableObject, IRepositoryQueryable, IUnitOfWorkRepository - where TEntity : class, IAggregateRoot + internal abstract class RepositoryBase : DisposableObject, IRepositoryQueryable, IUnitOfWorkRepository + where TEntity : class, IAggregateRoot { - private readonly IUnitOfWork _work; + private readonly IUnitOfWork _work; private readonly IRepositoryCacheProvider _cache; - protected RepositoryBase(IUnitOfWork work) + protected RepositoryBase(IUnitOfWork work) : this(work, RuntimeCacheProvider.Current) { } - internal RepositoryBase(IUnitOfWork work, IRepositoryCacheProvider cache) + internal RepositoryBase(IUnitOfWork work, IRepositoryCacheProvider cache) { - if (work == null) throw new ArgumentNullException("work"); - if (cache == null) throw new ArgumentNullException("cache"); - _work = work; + if (work == null) throw new ArgumentNullException("work"); + if (cache == null) throw new ArgumentNullException("cache"); + _work = work; _cache = cache; } /// /// Returns the Unit of Work added to the repository /// - protected internal IUnitOfWork UnitOfWork + protected internal IUnitOfWork UnitOfWork { get { return _work; } } @@ -74,7 +74,7 @@ namespace Umbraco.Core.Persistence.Repositories /// public virtual void Delete(TEntity entity) { - if(_work != null) + if (_work != null) { _work.RegisterRemoved(entity, this); } @@ -110,7 +110,7 @@ namespace Umbraco.Core.Persistence.Repositories asEntity.ResetDirtyProperties(false); } } - + return entity; } @@ -120,10 +120,10 @@ namespace Umbraco.Core.Persistence.Repositories var rEntity = _cache.GetById(typeof(TEntity), key); if (rEntity != null) { - return Attempt.Succeed((TEntity) rEntity); + return Attempt.Succeed((TEntity)rEntity); } return Attempt.Fail(); - } + } protected abstract IEnumerable PerformGetAll(params TId[] ids); /// @@ -133,56 +133,61 @@ namespace Umbraco.Core.Persistence.Repositories /// public IEnumerable GetAll(params TId[] ids) { + //ensure they are de-duplicated, easy win if people don't do this as this can cause many excess queries + ids = ids.Distinct() + //don't query by anything that is a default of T (like a zero) + //TODO: I think we should enabled this in case accidental calls are made to get all with invalid ids + //.Where(x => Equals(x, default(TId)) == false) + .ToArray(); + if (ids.Length > 2000) { throw new InvalidOperationException("Cannot perform a query with more than 2000 parameters"); } - TEntity[] entityCollection = {}; - if (ids.Any()) { var entities = _cache.GetByIds( - typeof (TEntity), ids.Select(id => id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString())).ToList()) + typeof(TEntity), ids.Select(id => id is int ? ConvertIdToGuid(id) : ConvertStringIdToGuid(id.ToString())).ToList()) .ToArray(); if (ids.Count().Equals(entities.Count()) && entities.Any(x => x == null) == false) return entities.Select(x => (TEntity)x); - - if (ids.Any()) - { - entityCollection = PerformGetAll(ids) - //ensure we don't include any null refs in the returned collection! - .WhereNotNull() - .ToArray(); - - //We need to put a threshold here! IF there's an insane amount of items - // coming back here we don't want to chuck it all into memory, this added cache here - // is more for convenience when paging stuff temporarily - - if (entityCollection.Length > 100) return entityCollection; - - foreach (var entity in entityCollection.Where(entity => entity != null)) - { - _cache.Save(typeof(TEntity), entity); - } - } } else { - var allEntities = _cache.GetAllByType(typeof (TEntity)).ToArray(); - + var allEntities = _cache.GetAllByType(typeof(TEntity)).ToArray(); + if (allEntities.Any()) { //Get count of all entities of current type (TEntity) to ensure cached result is correct var query = Query.Builder.Where(x => x.Id != 0); int totalCount = PerformCount(query); - if(allEntities.Count() == totalCount) + if (allEntities.Count() == totalCount) return allEntities.Select(x => (TEntity)x); } } + var entityCollection = PerformGetAll(ids) + //ensure we don't include any null refs in the returned collection! + .WhereNotNull() + .ToArray(); + + //We need to put a threshold here! IF there's an insane amount of items + // coming back here we don't want to chuck it all into memory, this added cache here + // is more for convenience when paging stuff temporarily + + if (entityCollection.Length > 100) return entityCollection; + + foreach (var entity in entityCollection) + { + if (entity != null) + { + _cache.Save(typeof(TEntity), entity); + } + } + return entityCollection; } @@ -212,7 +217,7 @@ namespace Umbraco.Core.Persistence.Repositories { return true; } - return PerformExists(id); + return PerformExists(id); } protected abstract int PerformCount(IQuery query); @@ -224,7 +229,7 @@ namespace Umbraco.Core.Persistence.Repositories public int Count(IQuery query) { return PerformCount(query); - } + } #endregion @@ -245,10 +250,10 @@ namespace Umbraco.Core.Persistence.Repositories { //if an exception is thrown we need to remove the entry from cache, this is ONLY a work around because of the way // that we cache entities: http://issues.umbraco.org/issue/U4-4259 - _cache.Delete(typeof (TEntity), entity); + _cache.Delete(typeof(TEntity), entity); throw; } - + } /// @@ -266,10 +271,10 @@ namespace Umbraco.Core.Persistence.Repositories { //if an exception is thrown we need to remove the entry from cache, this is ONLY a work around because of the way // that we cache entities: http://issues.umbraco.org/issue/U4-4259 - _cache.Delete(typeof (TEntity), entity); + _cache.Delete(typeof(TEntity), entity); throw; } - + } /// @@ -304,7 +309,7 @@ namespace Umbraco.Core.Persistence.Repositories protected virtual Guid ConvertIdToGuid(TId id) { int i = 0; - if(int.TryParse(id.ToString(), out i)) + if (int.TryParse(id.ToString(), out i)) { return i.ToGuid(); } @@ -316,15 +321,15 @@ namespace Umbraco.Core.Persistence.Repositories return id.EncodeAsGuid(); } - /// - /// Dispose disposable properties - /// - /// - /// Ensure the unit of work is disposed - /// - protected override void DisposeResources() - { - UnitOfWork.DisposeIfDisposable(); - } + /// + /// Dispose disposable properties + /// + /// + /// Ensure the unit of work is disposed + /// + protected override void DisposeResources() + { + UnitOfWork.DisposeIfDisposable(); + } } } \ No newline at end of file