Introduced IRelationRepository.SaveBulk to use internally when performance is important.

Fixed issue in RelationRepository.Save not populating Ids on LocalDB/SqlServer
This commit is contained in:
Bjarke Berg
2020-10-08 14:37:17 +02:00
parent 3171cdda70
commit 55db973e82
5 changed files with 99 additions and 12 deletions

View File

@@ -4,37 +4,81 @@ using Umbraco.Core.Models.Entities;
namespace Umbraco.Core.Models
{
public interface IRelation : IEntity, IRememberBeingDirty
public interface IRelation : IRememberBeingDirty, IRelationReadOnly
{
/// <summary>
/// Gets or sets the integer identifier of the entity.
/// </summary>
new int Id { get; set; }
/// <summary>
/// Gets or sets the Parent Id of the Relation (Source)
/// </summary>
[DataMember]
int ParentId { get; set; }
new int ParentId { get; set; }
[DataMember]
Guid ParentObjectType { get; set; }
new Guid ParentObjectType { get; set; }
/// <summary>
/// Gets or sets the Child Id of the Relation (Destination)
/// </summary>
[DataMember]
int ChildId { get; set; }
new int ChildId { get; set; }
[DataMember]
Guid ChildObjectType { get; set; }
new Guid ChildObjectType { get; set; }
/// <summary>
/// Gets or sets the <see cref="RelationType"/> for the Relation
/// </summary>
[DataMember]
IRelationType RelationType { get; set; }
new IRelationType RelationType { get; set; }
/// <summary>
/// Gets or sets a comment for the Relation
/// </summary>
[DataMember]
string Comment { get; set; }
new string Comment { get; set; }
/// <summary>
/// Gets the Id of the <see cref="RelationType"/> that this Relation is based on.
/// </summary>
[IgnoreDataMember]
new int RelationTypeId { get; }
}
public interface IRelationReadOnly : IEntity
{
/// <summary>
/// Gets the integer identifier of the entity.
/// </summary>
int Id { get; }
/// <summary>
/// Gets the Parent Id of the Relation (Source)
/// </summary>
int ParentId { get; }
Guid ParentObjectType { get; }
/// <summary>
/// Gets or sets the Child Id of the Relation (Destination)
/// </summary>
int ChildId { get; }
Guid ChildObjectType { get; }
/// <summary>
/// Gets the <see cref="RelationType"/> for the Relation
/// </summary>
IRelationType RelationType { get; }
/// <summary>
/// Gets a comment for the Relation
/// </summary>
string Comment { get; }
/// <summary>
/// Gets the Id of the <see cref="RelationType"/> that this Relation is based on.

View File

@@ -17,6 +17,12 @@ namespace Umbraco.Core.Persistence.Repositories
/// <param name="relations"></param>
void Save(IEnumerable<IRelation> relations);
/// <summary>
/// Persist multiple <see cref="IRelation"/> at once but Ids are not returned on created relations
/// </summary>
/// <param name="relations"></param>
void SaveBulk(IEnumerable<IRelationReadOnly> relations);
/// <summary>
/// Deletes all relations for a parent for any specified relation type alias
/// </summary>

View File

@@ -28,7 +28,7 @@ namespace Umbraco.Core.Persistence.Factories
}
}
public static RelationDto BuildDto(IRelation entity)
public static RelationDto BuildDto(IRelationReadOnly entity)
{
var dto = new RelationDto
{

View File

@@ -984,7 +984,7 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
}).WhereNotNull();
// Save bulk relations
RelationRepository.Save(toSave);
RelationRepository.SaveBulk(toSave);
}

View File

@@ -235,9 +235,11 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
},
RelationFactory.BuildDto); // value = DTO
// Use NPoco's own InsertBulk command which will automatically re-populate the new Ids on the entities, our own
// BulkInsertRecords does not cater for this.
Database.InsertBulk(entitiesAndDtos.Values);
foreach (var dto in entitiesAndDtos.Values)
{
Database.Insert(dto);
}
// All dtos now have IDs assigned
foreach (var de in entitiesAndDtos)
@@ -251,6 +253,41 @@ namespace Umbraco.Core.Persistence.Repositories.Implement
}
}
public void SaveBulk(IEnumerable<IRelationReadOnly> relations)
{
foreach (var hasIdentityGroup in relations.GroupBy(r => r.HasIdentity))
{
if (hasIdentityGroup.Key)
{
// Do updates, we can't really do a bulk update so this is still a 1 by 1 operation
// however we can bulk populate the object types. It might be possible to bulk update
// with SQL but would be pretty ugly and we're not really too worried about that for perf,
// it's the bulk inserts we care about.
foreach (var relation in hasIdentityGroup)
{
relation.UpdatingEntity();
var dto = RelationFactory.BuildDto(relation);
Database.Update(dto);
}
}
else
{
// Do bulk inserts
var entitiesAndDtos = hasIdentityGroup.ToDictionary(
r => // key = entity
{
r.AddingEntity();
return r;
},
RelationFactory.BuildDto); // value = DTO
Database.InsertBulk(entitiesAndDtos.Values);
}
}
}
public IEnumerable<IRelation> GetPagedRelationsByQuery(IQuery<IRelation> query, long pageIndex, int pageSize, out long totalRecords, Ordering ordering)
{
var sql = GetBaseQuery(false);