Fixes #U4-5529 properly. Reverts changes to RepositoryBase and alters queries instead. The check for Mandate.That(contentTypeIds.Any() was wrong when trying to select all conent types.

Maybe there's a better fix than this, feel free to update.
This commit is contained in:
Sebastiaan Janssen
2014-09-22 17:48:04 +02:00
parent e2ec9230b9
commit ef617fa5ed
2 changed files with 68 additions and 61 deletions

View File

@@ -764,7 +764,6 @@ AND umbracoNode.id <> @id",
out IDictionary<int, IEnumerable<AssociatedTemplate>> associatedTemplates,
out IDictionary<int, IEnumerable<int>> 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!

View File

@@ -14,29 +14,29 @@ namespace Umbraco.Core.Persistence.Repositories
/// </summary>
/// <typeparam name="TEntity">Type of <see cref="IAggregateRoot"/> entity for which the repository is used</typeparam>
/// <typeparam name="TId">Type of the Id used for this entity</typeparam>
internal abstract class RepositoryBase<TId, TEntity> : DisposableObject, IRepositoryQueryable<TId, TEntity>, IUnitOfWorkRepository
where TEntity : class, IAggregateRoot
internal abstract class RepositoryBase<TId, TEntity> : DisposableObject, IRepositoryQueryable<TId, TEntity>, 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;
}
/// <summary>
/// Returns the Unit of Work added to the repository
/// </summary>
protected internal IUnitOfWork UnitOfWork
protected internal IUnitOfWork UnitOfWork
{
get { return _work; }
}
@@ -74,7 +74,7 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="entity"></param>
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<TEntity>.Fail();
}
}
protected abstract IEnumerable<TEntity> PerformGetAll(params TId[] ids);
/// <summary>
@@ -133,56 +133,61 @@ namespace Umbraco.Core.Persistence.Repositories
/// <returns></returns>
public IEnumerable<TEntity> 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<TEntity>.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<TEntity> query);
@@ -224,7 +229,7 @@ namespace Umbraco.Core.Persistence.Repositories
public int Count(IQuery<TEntity> 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;
}
}
/// <summary>
@@ -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;
}
}
/// <summary>
@@ -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();
}
/// <summary>
/// Dispose disposable properties
/// </summary>
/// <remarks>
/// Ensure the unit of work is disposed
/// </remarks>
protected override void DisposeResources()
{
UnitOfWork.DisposeIfDisposable();
}
/// <summary>
/// Dispose disposable properties
/// </summary>
/// <remarks>
/// Ensure the unit of work is disposed
/// </remarks>
protected override void DisposeResources()
{
UnitOfWork.DisposeIfDisposable();
}
}
}