diff --git a/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs b/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs index a73b7fc3d7..edfb53526c 100644 --- a/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs +++ b/src/Umbraco.Core/Persistence/Repositories/EntityRepository.cs @@ -139,11 +139,9 @@ namespace Umbraco.Core.Persistence.Repositories public virtual IEnumerable GetAll(Guid objectTypeId, params int[] ids) { - //TODO: Fix the n+1 query! - if (ids.Any()) { - return ids.Select(id => Get(id, objectTypeId)); + return PerformGetAll(objectTypeId, sql1 => sql1.Where(" umbracoNode.id in (@ids)", ids)); } else { @@ -153,11 +151,9 @@ namespace Umbraco.Core.Persistence.Repositories public virtual IEnumerable GetAll(Guid objectTypeId, params Guid[] keys) { - //TODO: Fix the n+1 query! - if (keys.Any()) { - return keys.Select(key => GetByKey(key, objectTypeId)); + return PerformGetAll(objectTypeId, sql1 => sql1.Where(" umbracoNode.uniqueID in (@keys)", keys)); } else { @@ -165,13 +161,11 @@ namespace Umbraco.Core.Persistence.Repositories } } - private IEnumerable PerformGetAll(Guid objectTypeId) + private IEnumerable PerformGetAll(Guid objectTypeId, Action filter = null) { - //TODO: Fix the n+1 query! - bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document); bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media); - var sql = GetFullSqlForEntityType(isContent, isMedia, objectTypeId, string.Empty); + var sql = GetFullSqlForEntityType(isContent, isMedia, objectTypeId, filter); var factory = new UmbracoEntityFactory(); @@ -199,8 +193,8 @@ namespace Umbraco.Core.Persistence.Repositories public virtual IEnumerable GetByQuery(IQuery query) { - var wheres = string.Concat(" AND ", string.Join(" AND ", ((Query) query).WhereClauses())); - var sqlClause = GetBase(false, false, wheres); + var wheres = string.Join(" AND ", ((Query) query).WhereClauses()); + var sqlClause = GetBase(false, false, sql1 => sql1.Where(wheres)); var translator = new SqlTranslator(sqlClause, query); var sql = translator.Translate().Append(GetGroupBy(false, false)); @@ -217,9 +211,9 @@ namespace Umbraco.Core.Persistence.Repositories bool isContent = objectTypeId == new Guid(Constants.ObjectTypes.Document); bool isMedia = objectTypeId == new Guid(Constants.ObjectTypes.Media); - var wheres = string.Concat(" AND ", string.Join(" AND ", ((Query)query).WhereClauses())); - - var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, wheres, objectTypeId); + var wheres = string.Join(" AND ", ((Query)query).WhereClauses()); + + var sqlClause = GetBaseWhere(GetBase, isContent, isMedia, sql1 => sql1.Where(wheres), objectTypeId); var translator = new SqlTranslator(sqlClause, query); var entitySql = translator.Translate(); @@ -228,7 +222,7 @@ namespace Umbraco.Core.Persistence.Repositories if (isMedia) { - var mediaSql = GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)), wheres); + var mediaSql = GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)), sql => sql.Where(wheres)); //treat media differently for now //TODO: We should really use this methodology for Content/Members too!! since it includes properties and ALL of the dynamic db fields @@ -267,16 +261,16 @@ namespace Umbraco.Core.Persistence.Repositories return GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false))); } - protected Sql GetFullSqlForEntityType(bool isContent, bool isMedia, Guid objectTypeId, string additionalWhereClause) + protected Sql GetFullSqlForEntityType(bool isContent, bool isMedia, Guid objectTypeId, Action filter) { - var entitySql = GetBaseWhere(GetBase, isContent, isMedia, additionalWhereClause, objectTypeId); + var entitySql = GetBaseWhere(GetBase, isContent, isMedia, filter, objectTypeId); if (isMedia == false) return entitySql.Append(GetGroupBy(isContent, false)); - return GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false))); + return GetFullSqlForMedia(entitySql.Append(GetGroupBy(isContent, true, false)), filter); } - private Sql GetFullSqlForMedia(Sql entitySql, string additionWhereStatement = "") + private Sql GetFullSqlForMedia(Sql entitySql, Action filter = null) { //this will add any dataNvarchar property to the output which can be added to the additional properties @@ -289,7 +283,12 @@ namespace Umbraco.Core.Persistence.Repositories .On(dto => dto.Id, dto => dto.PropertyTypeId) .InnerJoin() .On(dto => dto.DataTypeId, dto => dto.DataTypeId) - .Where("umbracoNode.nodeObjectType = @nodeObjectType" + additionWhereStatement, new {nodeObjectType = Constants.ObjectTypes.Media}); + .Where("umbracoNode.nodeObjectType = @nodeObjectType", new {nodeObjectType = Constants.ObjectTypes.Media}); + + if (filter != null) + { + filter(joinSql); + } //We're going to create a query to query against the entity SQL // because we cannot group by nText columns and we have a COUNT in the entitySql we cannot simply left join @@ -305,7 +304,7 @@ namespace Umbraco.Core.Persistence.Repositories return wrappedSql; } - protected virtual Sql GetBase(bool isContent, bool isMedia, string additionWhereStatement = "") + protected virtual Sql GetBase(bool isContent, bool isMedia, Action customFilter) { var columns = new List { @@ -353,43 +352,48 @@ namespace Umbraco.Core.Persistence.Repositories .On("umbracoNode.id = latest.nodeId"); } + if (customFilter != null) + { + customFilter(entitySql); + } + return entitySql; } - protected virtual Sql GetBaseWhere(Func baseQuery, bool isContent, bool isMedia, string additionWhereStatement, Guid nodeObjectType) + protected virtual Sql GetBaseWhere(Func, Sql> baseQuery, bool isContent, bool isMedia, Action filter, Guid nodeObjectType) { - var sql = baseQuery(isContent, isMedia, additionWhereStatement) + var sql = baseQuery(isContent, isMedia, filter) .Where("umbracoNode.nodeObjectType = @NodeObjectType", new { NodeObjectType = nodeObjectType }); return sql; } - protected virtual Sql GetBaseWhere(Func baseQuery, bool isContent, bool isMedia, int id) + protected virtual Sql GetBaseWhere(Func, Sql> baseQuery, bool isContent, bool isMedia, int id) { - var sql = baseQuery(isContent, isMedia, " AND umbracoNode.id = '"+ id +"'") + var sql = baseQuery(isContent, isMedia, null) .Where("umbracoNode.id = @Id", new { Id = id }) .Append(GetGroupBy(isContent, isMedia)); return sql; } - protected virtual Sql GetBaseWhere(Func baseQuery, bool isContent, bool isMedia, Guid key) + protected virtual Sql GetBaseWhere(Func, Sql> baseQuery, bool isContent, bool isMedia, Guid key) { - var sql = baseQuery(isContent, isMedia, " AND umbracoNode.uniqueID = '" + key + "'") + var sql = baseQuery(isContent, isMedia, null) .Where("umbracoNode.uniqueID = @UniqueID", new { UniqueID = key }) .Append(GetGroupBy(isContent, isMedia)); return sql; } - protected virtual Sql GetBaseWhere(Func baseQuery, bool isContent, bool isMedia, Guid nodeObjectType, int id) + protected virtual Sql GetBaseWhere(Func, Sql> baseQuery, bool isContent, bool isMedia, Guid nodeObjectType, int id) { - var sql = baseQuery(isContent, isMedia, " AND umbracoNode.id = '"+ id +"'") + var sql = baseQuery(isContent, isMedia, null) .Where("umbracoNode.id = @Id AND umbracoNode.nodeObjectType = @NodeObjectType", new {Id = id, NodeObjectType = nodeObjectType}); return sql; } - protected virtual Sql GetBaseWhere(Func baseQuery, bool isContent, bool isMedia, Guid nodeObjectType, Guid key) + protected virtual Sql GetBaseWhere(Func, Sql> baseQuery, bool isContent, bool isMedia, Guid nodeObjectType, Guid key) { - var sql = baseQuery(isContent, isMedia, " AND umbracoNode.uniqueID = '" + key + "'") + var sql = baseQuery(isContent, isMedia, null) .Where("umbracoNode.uniqueID = @UniqueID AND umbracoNode.nodeObjectType = @NodeObjectType", new { UniqueID = key, NodeObjectType = nodeObjectType }); return sql;