Gets entity repository to be able to return a mix of object types

This commit is contained in:
Shannon
2019-11-05 15:05:51 +11:00
parent 412eadd9a3
commit fff3d2648f
19 changed files with 273 additions and 72 deletions

View File

@@ -108,6 +108,9 @@ namespace Umbraco.Core.Models
[IgnoreDataMember]
public int VersionId { get; set; }
[DataMember]
public Guid NodeObjectType { get; internal set; }
/// <summary>
/// Integer Id of the default ContentType
/// </summary>

View File

@@ -113,6 +113,9 @@ namespace Umbraco.Core.Models
OnPropertyChanged(nameof(PropertyTypes));
}
[DataMember]
public Guid NodeObjectType { get; internal set; }
/// <summary>
/// The Alias of the ContentType
/// </summary>

View File

@@ -65,6 +65,9 @@ namespace Umbraco.Core.Models
[DataMember]
public string EditorAlias => _editor.Alias;
[DataMember]
public Guid NodeObjectType { get; internal set; }
/// <inheritdoc />
[DataMember]
public ValueStorageType DatabaseType

View File

@@ -24,7 +24,7 @@
/// Sets the parent entity.
/// </summary>
/// <remarks>Use this method to set the parent entity when the parent entity is known, but has not
/// been persistent and does not yet have an identity. The parent identifier will we retrieved
/// been persistent and does not yet have an identity. The parent identifier will be retrieved
/// from the parent entity when needed. If the parent entity still does not have an entity by that
/// time, an exception will be thrown by <see cref="ParentId"/> getter.</remarks>
void SetParent(ITreeEntity parent);
@@ -53,4 +53,4 @@
/// </remarks>
bool Trashed { get; }
}
}
}

View File

@@ -1,4 +1,5 @@
using System.Collections.Generic;
using System;
using System.Collections.Generic;
namespace Umbraco.Core.Models.Entities
{
@@ -11,5 +12,7 @@ namespace Umbraco.Core.Models.Entities
/// <para>An IUmbracoEntity can participate in notifications.</para>
/// </remarks>
public interface IUmbracoEntity : ITreeEntity, IRememberBeingDirty
{ }
{
Guid NodeObjectType { get; }
}
}

View File

@@ -62,6 +62,8 @@ namespace Umbraco.Core.Models
/// </summary>
public Guid ContainerObjectType => ObjectTypeMap[_containedObjectType];
Guid IUmbracoEntity.NodeObjectType => ContainerObjectType;
/// <summary>
/// Gets the container object type corresponding to a contained object type.
/// </summary>

View File

@@ -44,11 +44,14 @@ namespace Umbraco.Core.Models
Name = contentType.Name;
AllowedAsRoot = contentType.AllowedAsRoot;
IsElement = contentType.IsElement;
NodeObjectType = contentType.NodeObjectType;
}
/// <inheritdoc />
public string Alias { get; }
public Guid NodeObjectType { get; }
public int Id { get; }
/// <inheritdoc />

View File

@@ -34,7 +34,7 @@ namespace Umbraco.Core.Persistence.Factories
content.VersionId = contentVersionDto.Id;
content.Name = contentVersionDto.Text;
content.NodeObjectType = nodeDto.NodeObjectType ?? Guid.Empty;
content.Path = nodeDto.Path;
content.Level = nodeDto.Level;
content.ParentId = nodeDto.ParentId;

View File

@@ -107,6 +107,7 @@ namespace Umbraco.Core.Persistence.Factories
{
entity.Id = dto.NodeDto.NodeId;
entity.Key = dto.NodeDto.UniqueId;
entity.NodeObjectType = dto.NodeDto.NodeObjectType ?? Guid.Empty;
entity.Alias = dto.Alias;
entity.Name = dto.NodeDto.Text;
entity.Icon = dto.Icon;

View File

@@ -28,6 +28,7 @@ namespace Umbraco.Core.Persistence.Factories
dataType.DisableChangeTracking();
dataType.CreateDate = dto.NodeDto.CreateDate;
dataType.NodeObjectType = dto.NodeDto.NodeObjectType ?? Guid.Empty;
dataType.DatabaseType = dto.DbType.EnumParse<ValueStorageType>(true);
dataType.Id = dto.NodeId;
dataType.Key = dto.NodeDto.UniqueId;

View File

@@ -24,6 +24,7 @@ namespace Umbraco.Core.Persistence.Mappers
DefineMap<IUmbracoEntity, NodeDto>(nameof(IUmbracoEntity.Trashed), nameof(NodeDto.Trashed));
DefineMap<IUmbracoEntity, NodeDto>(nameof(IUmbracoEntity.Key), nameof(NodeDto.UniqueId));
DefineMap<IUmbracoEntity, NodeDto>(nameof(IUmbracoEntity.CreatorId), nameof(NodeDto.UserId));
DefineMap<IUmbracoEntity, NodeDto>(nameof(IUmbracoEntity.NodeObjectType), nameof(NodeDto.NodeObjectType));
}
}
}

View File

@@ -15,10 +15,22 @@ namespace Umbraco.Core.Persistence.Repositories
IEntitySlim Get(int id, Guid objectTypeId);
IEntitySlim Get(Guid key, Guid objectTypeId);
IEnumerable<IEntitySlim> GetAll(Guid objectType, params int[] ids);
IEnumerable<IEntitySlim> GetAll(Guid objectType, params int[] ids);
IEnumerable<IEntitySlim> GetAll(Guid objectType, params Guid[] keys);
/// <summary>
/// Gets entities for a query
/// </summary>
/// <param name="query"></param>
/// <returns></returns>
IEnumerable<IEntitySlim> GetByQuery(IQuery<IUmbracoEntity> query);
/// <summary>
/// Gets entities for a query and a specific object type allowing the query to be slightly more optimized
/// </summary>
/// <param name="query"></param>
/// <param name="objectType"></param>
/// <returns></returns>
IEnumerable<IEntitySlim> GetByQuery(IQuery<IUmbracoEntity> query, Guid objectType);
UmbracoObjectTypes GetObjectType(int id);
@@ -30,7 +42,36 @@ namespace Umbraco.Core.Persistence.Repositories
bool Exists(int id);
bool Exists(Guid key);
/// <summary>
/// Gets paged entities for a query and a subset of object types
/// </summary>
/// <param name="query"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <param name="filter"></param>
/// <param name="ordering"></param>
/// <returns>
/// A collection of mixed entity types which would be of type <see cref="IEntitySlim"/>, <see cref="IDocumentEntitySlim"/>, <see cref="IMediaEntitySlim"/>,
/// <see cref="IMemberEntitySlim"/>
/// </returns>
IEnumerable<IEntitySlim> GetPagedResultsByQuery(IQuery<IUmbracoEntity> query, Guid[] objectTypes, long pageIndex, int pageSize, out long totalRecords,
IQuery<IUmbracoEntity> filter, Ordering ordering);
/// <summary>
/// Gets paged entities for a query and a specific object type
/// </summary>
/// <param name="query"></param>
/// <param name="objectType"></param>
/// <param name="pageIndex"></param>
/// <param name="pageSize"></param>
/// <param name="totalRecords"></param>
/// <param name="filter"></param>
/// <param name="ordering"></param>
/// <returns></returns>
IEnumerable<IEntitySlim> GetPagedResultsByQuery(IQuery<IUmbracoEntity> query, Guid objectType, long pageIndex, int pageSize, out long totalRecords,
IQuery<IUmbracoEntity> filter, Ordering ordering);
}
}

View File

@@ -36,26 +36,70 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
#region Repository
// get a page of entities
//public IEnumerable<IEntitySlim> GetPagedResults(IDictionary<Guid, IEnumerable<int>> typesAndIds, long pageIndex, int pageSize, out long totalRecords, Ordering ordering)
//{
// var isContent = typesAndIds.Keys.Any(objectType => objectType == Constants.ObjectTypes.Document || objectType == Constants.ObjectTypes.DocumentBlueprint);
// var isMedia = typesAndIds.Keys.Any(objectType => objectType == Constants.ObjectTypes.Media);
// var isMember = typesAndIds.Keys.Any(objectType => objectType == Constants.ObjectTypes.Member);
// var sql = GetBase(isContent, isMedia, isMember, null, false)
// .WhereIn<NodeDto>(x => x.NodeObjectType, typesAndIds.Keys);
// ordering = ordering ?? Ordering.ByDefault();
// sql = AddGroupBy(isContent, isMedia, isMember, sql, ordering.IsEmpty);
// if (!ordering.IsEmpty)
// {
// // apply ordering
// ApplyOrdering(ref sql, ordering);
// }
// // TODO: we should be able to do sql = sql.OrderBy(x => Alias(x.NodeId, "NodeId")); but we can't because the OrderBy extension don't support Alias currently
// //no matter what we always must have node id ordered at the end
// sql = ordering.Direction == Direction.Ascending ? sql.OrderBy("NodeId") : sql.OrderByDescending("NodeId");
// // for content we must query for ContentEntityDto entities to produce the correct culture variant entity names
// var pageIndexToFetch = pageIndex + 1;
// IEnumerable<BaseDto> dtos;
// var page = Database.Page<GenericContentEntityDto>(pageIndexToFetch, pageSize, sql);
// dtos = page.Items;
// totalRecords = page.TotalItems;
// var entities = dtos.Select(BuildEntity).ToArray();
// BuildVariants(entities.OfType<DocumentEntitySlim>());
// return entities;
//}
public IEnumerable<IEntitySlim> GetPagedResultsByQuery(IQuery<IUmbracoEntity> query, Guid objectType, long pageIndex, int pageSize, out long totalRecords,
IQuery<IUmbracoEntity> filter, Ordering ordering)
{
var isContent = objectType == Constants.ObjectTypes.Document || objectType == Constants.ObjectTypes.DocumentBlueprint;
var isMedia = objectType == Constants.ObjectTypes.Media;
var isMember = objectType == Constants.ObjectTypes.Member;
query = query.Where(x => x.NodeObjectType == objectType);
return GetPagedResultsByQuery(query, new[] { objectType }, pageIndex, pageSize, out totalRecords, filter, ordering);
}
// get a page of entities
public IEnumerable<IEntitySlim> GetPagedResultsByQuery(IQuery<IUmbracoEntity> query, Guid[] objectTypes, long pageIndex, int pageSize, out long totalRecords,
IQuery<IUmbracoEntity> filter, Ordering ordering)
{
var isContent = objectTypes.Any(objectType => objectType == Constants.ObjectTypes.Document || objectType == Constants.ObjectTypes.DocumentBlueprint);
var isMedia = objectTypes.Any(objectType => objectType == Constants.ObjectTypes.Media);
var isMember = objectTypes.Any(objectType => objectType == Constants.ObjectTypes.Member);
var sql = GetBaseWhere(isContent, isMedia, isMember, false, x =>
{
if (filter == null) return;
foreach (var filterClause in filter.GetWhereClauses())
x.Where(filterClause.Item1, filterClause.Item2);
}, objectType);
}, objectTypes);
ordering = ordering ?? Ordering.ByDefault();
var translator = new SqlTranslator<IUmbracoEntity>(sql, query);
sql = translator.Translate();
sql = AddGroupBy(isContent, isMedia, isMember, sql, ordering.IsEmpty);
sql = AddGroupBy(true, true, true, sql, ordering.IsEmpty);
if (!ordering.IsEmpty)
{
@@ -70,35 +114,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
// for content we must query for ContentEntityDto entities to produce the correct culture variant entity names
var pageIndexToFetch = pageIndex + 1;
IEnumerable<BaseDto> dtos;
if(isContent)
{
var page = Database.Page<ContentEntityDto>(pageIndexToFetch, pageSize, sql);
dtos = page.Items;
totalRecords = page.TotalItems;
}
else if (isMedia)
{
var page = Database.Page<MediaEntityDto>(pageIndexToFetch, pageSize, sql);
dtos = page.Items;
totalRecords = page.TotalItems;
}
else if (isMember)
{
var page = Database.Page<MemberEntityDto>(pageIndexToFetch, pageSize, sql);
dtos = page.Items;
totalRecords = page.TotalItems;
}
else
{
var page = Database.Page<BaseDto>(pageIndexToFetch, pageSize, sql);
dtos = page.Items;
totalRecords = page.TotalItems;
}
var page = Database.Page<GenericContentEntityDto>(pageIndexToFetch, pageSize, sql);
dtos = page.Items;
totalRecords = page.TotalItems;
var entities = dtos.Select(x => BuildEntity(isContent, isMedia, isMember, x)).ToArray();
var entities = dtos.Select(BuildEntity).ToArray();
if (isContent)
BuildVariants(entities.Cast<DocumentEntitySlim>());
BuildVariants(entities.OfType<DocumentEntitySlim>());
return entities;
}
@@ -107,7 +129,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
{
var sql = GetBaseWhere(false, false, false, false, key);
var dto = Database.FirstOrDefault<BaseDto>(sql);
return dto == null ? null : BuildEntity(false, false, false, dto);
return dto == null ? null : BuildEntity(dto);
}
@@ -116,7 +138,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
//isContent is going to return a 1:M result now with the variants so we need to do different things
if (isContent)
{
var cdtos = Database.Fetch<ContentEntityDto>(sql);
var cdtos = Database.Fetch<DocumentEntityDto>(sql);
return cdtos.Count == 0 ? null : BuildVariants(BuildDocumentEntity(cdtos[0]));
}
@@ -127,7 +149,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
if (dto == null) return null;
var entity = BuildEntity(false, isMedia, isMember, dto);
var entity = BuildEntity(dto);
return entity;
}
@@ -146,7 +168,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
{
var sql = GetBaseWhere(false, false, false, false, id);
var dto = Database.FirstOrDefault<BaseDto>(sql);
return dto == null ? null : BuildEntity(false, false, false, dto);
return dto == null ? null : BuildEntity(dto);
}
public IEntitySlim Get(int id, Guid objectTypeId)
@@ -178,7 +200,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
//isContent is going to return a 1:M result now with the variants so we need to do different things
if (isContent)
{
var cdtos = Database.Fetch<ContentEntityDto>(sql);
var cdtos = Database.Fetch<DocumentEntityDto>(sql);
return cdtos.Count == 0
? Enumerable.Empty<IEntitySlim>()
@@ -189,7 +211,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
? (IEnumerable<BaseDto>)Database.Fetch<MediaEntityDto>(sql)
: Database.Fetch<BaseDto>(sql);
var entities = dtos.Select(x => BuildEntity(false, isMedia, isMember, x)).ToArray();
var entities = dtos.Select(BuildEntity).ToArray();
return entities;
}
@@ -233,7 +255,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
var sql = translator.Translate();
sql = AddGroupBy(false, false, false, sql, true);
var dtos = Database.Fetch<BaseDto>(sql);
return dtos.Select(x => BuildEntity(false, false, false, x)).ToList();
return dtos.Select(BuildEntity).ToList();
}
public IEnumerable<IEntitySlim> GetByQuery(IQuery<IUmbracoEntity> query, Guid objectType)
@@ -242,7 +264,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
var isMedia = objectType == Constants.ObjectTypes.Media;
var isMember = objectType == Constants.ObjectTypes.Member;
var sql = GetBaseWhere(isContent, isMedia, isMember, false, null, objectType);
var sql = GetBaseWhere(isContent, isMedia, isMember, false, null, new[] { objectType });
var translator = new SqlTranslator<IUmbracoEntity>(sql, query);
sql = translator.Translate();
@@ -356,14 +378,14 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
// gets the full sql for a given object type, with a given filter
protected Sql<ISqlContext> GetFullSqlForEntityType(bool isContent, bool isMedia, bool isMember, Guid objectType, Action<Sql<ISqlContext>> filter)
{
var sql = GetBaseWhere(isContent, isMedia, isMember, false, filter, objectType);
var sql = GetBaseWhere(isContent, isMedia, isMember, false, filter, new[] { objectType });
return AddGroupBy(isContent, isMedia, isMember, sql, true);
}
// gets the base SELECT + FROM [+ filter] sql
// always from the 'current' content version
protected Sql<ISqlContext> GetBase(bool isContent, bool isMedia, bool isMember, Action<Sql<ISqlContext>> filter, bool isCount = false)
{
{
var sql = Sql();
if (isCount)
@@ -401,15 +423,15 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
if (isContent || isMedia || isMember)
{
sql
.InnerJoin<ContentVersionDto>().On<NodeDto, ContentVersionDto>((left, right) => left.NodeId == right.NodeId && right.Current)
.InnerJoin<ContentDto>().On<NodeDto, ContentDto>((left, right) => left.NodeId == right.NodeId)
.InnerJoin<ContentTypeDto>().On<ContentDto, ContentTypeDto>((left, right) => left.ContentTypeId == right.NodeId);
.LeftJoin<ContentVersionDto>().On<NodeDto, ContentVersionDto>((left, right) => left.NodeId == right.NodeId && right.Current)
.LeftJoin<ContentDto>().On<NodeDto, ContentDto>((left, right) => left.NodeId == right.NodeId)
.LeftJoin<ContentTypeDto>().On<ContentDto, ContentTypeDto>((left, right) => left.ContentTypeId == right.NodeId);
}
if (isContent)
{
sql
.InnerJoin<DocumentDto>().On<NodeDto, DocumentDto>((left, right) => left.NodeId == right.NodeId);
.LeftJoin<DocumentDto>().On<NodeDto, DocumentDto>((left, right) => left.NodeId == right.NodeId);
}
if (isMedia)
@@ -433,10 +455,10 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
// gets the base SELECT + FROM [+ filter] + WHERE sql
// for a given object type, with a given filter
protected Sql<ISqlContext> GetBaseWhere(bool isContent, bool isMedia, bool isMember, bool isCount, Action<Sql<ISqlContext>> filter, Guid objectType)
protected Sql<ISqlContext> GetBaseWhere(bool isContent, bool isMedia, bool isMember, bool isCount, Action<Sql<ISqlContext>> filter, Guid[] objectTypes)
{
return GetBase(isContent, isMedia, isMember, filter, isCount)
.Where<NodeDto>(x => x.NodeObjectType == objectType);
.WhereIn<NodeDto>(x => x.NodeObjectType, objectTypes);
}
// gets the base SELECT + FROM + WHERE sql
@@ -510,8 +532,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
if (sql == null) throw new ArgumentNullException(nameof(sql));
if (ordering == null) throw new ArgumentNullException(nameof(ordering));
// TODO: although this works for name, it probably doesn't work for others without an alias of some sort
var orderBy = ordering.OrderBy;
// TODO: although the default ordering string works for name, it wont work for others without a table or an alias of some sort
// As more things are attempted to be sorted we'll prob have to add more expressions here
var orderBy = ordering.OrderBy.ToUpperInvariant() switch
{
"PATH" => SqlSyntax.GetQuotedColumn(NodeDto.TableName, "path"),
_ => ordering.OrderBy
};
if (ordering.Direction == Direction.Ascending)
sql.OrderBy(orderBy);
@@ -524,9 +551,17 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
#region Classes
/// <summary>
/// The DTO used to fetch results for a content item with its variation info
/// The DTO used to fetch results for a generic content item which could be either a document, media or a member
/// </summary>
private class ContentEntityDto : BaseDto
private class GenericContentEntityDto : DocumentEntityDto
{
public string MediaPath { get; set; }
}
/// <summary>
/// The DTO used to fetch results for a document item with its variation info
/// </summary>
private class DocumentEntityDto : BaseDto
{
public ContentVariation Variations { get; set; }
@@ -534,11 +569,17 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
public bool Edited { get; set; }
}
/// <summary>
/// The DTO used to fetch results for a media item with its media path info
/// </summary>
private class MediaEntityDto : BaseDto
{
public string MediaPath { get; set; }
}
/// <summary>
/// The DTO used to fetch results for a member item
/// </summary>
private class MemberEntityDto : BaseDto
{
}
@@ -589,13 +630,13 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
#region Factory
private EntitySlim BuildEntity(bool isContent, bool isMedia, bool isMember, BaseDto dto)
private EntitySlim BuildEntity(BaseDto dto)
{
if (isContent)
if (dto.NodeObjectType == Constants.ObjectTypes.Document)
return BuildDocumentEntity(dto);
if (isMedia)
if (dto.NodeObjectType == Constants.ObjectTypes.Media)
return BuildMediaEntity(dto);
if (isMember)
if (dto.NodeObjectType == Constants.ObjectTypes.Member)
return BuildMemberEntity(dto);
// EntitySlim does not track changes
@@ -650,7 +691,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
var entity = new DocumentEntitySlim();
BuildContentEntity(entity, dto);
if (dto is ContentEntityDto contentDto)
if (dto is DocumentEntityDto contentDto)
{
// fill in the invariant info
entity.Edited = contentDto.Edited;

View File

@@ -0,0 +1,95 @@
using System.Collections.Generic;
using System.Linq;
using NUnit.Framework;
using Umbraco.Core;
using Umbraco.Core.Models;
using Umbraco.Core.Models.Entities;
using Umbraco.Core.Persistence;
using Umbraco.Core.Persistence.Repositories.Implement;
using Umbraco.Core.Scoping;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Entities;
using Umbraco.Tests.Testing;
namespace Umbraco.Tests.Persistence.Repositories
{
[TestFixture]
[UmbracoTest(Mapper = true, Database = UmbracoTestOptions.Database.NewSchemaPerTest)]
public class EntityRepositoryTest : TestWithDatabaseBase
{
private EntityRepository CreateRepository(IScopeAccessor scopeAccessor)
{
var entityRepository = new EntityRepository(scopeAccessor);
return entityRepository;
}
[Test]
public void Get_Paged_Mixed_Entities_By_Ids()
{
//Create content
var createdContent = new List<IContent>();
var contentType = MockedContentTypes.CreateBasicContentType("blah");
ServiceContext.ContentTypeService.Save(contentType);
for (int i = 0; i < 10; i++)
{
var c1 = MockedContent.CreateBasicContent(contentType);
ServiceContext.ContentService.Save(c1);
createdContent.Add(c1);
}
//Create media
var createdMedia = new List<IMedia>();
var imageType = MockedContentTypes.CreateImageMediaType("myImage");
ServiceContext.MediaTypeService.Save(imageType);
for (int i = 0; i < 10; i++)
{
var c1 = MockedMedia.CreateMediaImage(imageType, -1);
ServiceContext.MediaService.Save(c1);
createdMedia.Add(c1);
}
// Create members
var memberType = MockedContentTypes.CreateSimpleMemberType("simple");
ServiceContext.MemberTypeService.Save(memberType);
var createdMembers = MockedMember.CreateSimpleMember(memberType, 10).ToList();
ServiceContext.MemberService.Save(createdMembers);
var provider = TestObjects.GetScopeProvider(Logger);
using (var scope = provider.CreateScope())
{
var repo = CreateRepository((IScopeAccessor)provider);
var ids = createdContent.Select(x => x.Id).Concat(createdMedia.Select(x => x.Id)).Concat(createdMembers.Select(x => x.Id));
var objectTypes = new[] { Constants.ObjectTypes.Document, Constants.ObjectTypes.Media, Constants.ObjectTypes.Member };
var query = SqlContext.Query<IUmbracoEntity>()
.WhereIn(e => e.Id, ids);
var entities = repo.GetPagedResultsByQuery(query, objectTypes, 0, 20, out var totalRecords, null, null).ToList();
Assert.AreEqual(20, entities.Count);
Assert.AreEqual(30, totalRecords);
//add the next page
entities.AddRange(repo.GetPagedResultsByQuery(query, objectTypes, 1, 20, out totalRecords, null, null));
Assert.AreEqual(30, entities.Count);
Assert.AreEqual(30, totalRecords);
var contentEntities = entities.OfType<IDocumentEntitySlim>().ToList();
var mediaEntities = entities.OfType<IMediaEntitySlim>().ToList();
var memberEntities = entities.OfType<IMemberEntitySlim>().ToList();
Assert.AreEqual(10, contentEntities.Count);
Assert.AreEqual(10, mediaEntities.Count);
Assert.AreEqual(10, memberEntities.Count);
}
}
}
}

View File

@@ -140,6 +140,7 @@
<Compile Include="Models\VariationTests.cs" />
<Compile Include="Persistence\Mappers\MapperTestBase.cs" />
<Compile Include="Persistence\Repositories\DocumentRepositoryTest.cs" />
<Compile Include="Persistence\Repositories\EntityRepositoryTest.cs" />
<Compile Include="PublishedContent\NuCacheChildrenTests.cs" />
<Compile Include="PublishedContent\PublishedContentLanguageVariantTests.cs" />
<Compile Include="PublishedContent\PublishedContentSnapshotTestBase.cs" />

View File

@@ -662,6 +662,9 @@ namespace Umbraco.Web.Editors
if (pageSize <= 0)
throw new HttpResponseException(HttpStatusCode.NotFound);
// re-normalize since NULL can be passed in
filter = filter ?? string.Empty;
var objectType = ConvertToObjectType(type);
if (objectType.HasValue)
{

View File

@@ -226,11 +226,11 @@ namespace Umbraco.Web.Models.Mapping
{
switch (entity)
{
case ContentEntitySlim contentEntity:
// NOTE: this case covers both content and media entities
return contentEntity.ContentTypeIcon;
case MemberEntitySlim memberEntity:
case IMemberEntitySlim memberEntity:
return memberEntity.ContentTypeIcon.IfNullOrWhiteSpace(Constants.Icons.Member);
case IContentEntitySlim contentEntity:
// NOTE: this case covers both content and media entities
return contentEntity.ContentTypeIcon;
}
return null;

View File

@@ -380,8 +380,8 @@ namespace Umbraco.Web.Models.Mapping
.ToDictionary(x => x.Key, x => (IEnumerable<Permission>)x.ToArray());
}
private static string MapContentTypeIcon(EntitySlim entity)
=> entity is ContentEntitySlim contentEntity ? contentEntity.ContentTypeIcon : null;
private static string MapContentTypeIcon(IEntitySlim entity)
=> entity is IContentEntitySlim contentEntity ? contentEntity.ContentTypeIcon : null;
private IEnumerable<EntityBasic> GetStartNodes(int[] startNodeIds, UmbracoObjectTypes objectType, string localizedKey, MapperContext context)
{

View File

@@ -47,7 +47,7 @@ namespace Umbraco.Web.Trees
if (id == Constants.System.RootString)
{
//get all blueprint content types
var contentTypeAliases = entities.Select(x => ((ContentEntitySlim) x).ContentTypeAlias).Distinct();
var contentTypeAliases = entities.Select(x => ((IContentEntitySlim) x).ContentTypeAlias).Distinct();
//get the ids
var contentTypeIds = Services.ContentTypeService.GetAllContentTypeIds(contentTypeAliases.ToArray()).ToArray();
@@ -75,7 +75,7 @@ namespace Umbraco.Web.Trees
var ct = Services.ContentTypeService.Get(intId.Result);
if (ct == null) return nodes;
var blueprintsForDocType = entities.Where(x => ct.Alias == ((ContentEntitySlim) x).ContentTypeAlias);
var blueprintsForDocType = entities.Where(x => ct.Alias == ((IContentEntitySlim) x).ContentTypeAlias);
nodes.AddRange(blueprintsForDocType
.Select(entity =>
{