Wrap calls to map in scopes

This commit is contained in:
Mole
2021-03-16 14:18:17 +01:00
parent 653bf52a1c
commit 68c4ce2008
3 changed files with 77 additions and 18 deletions

View File

@@ -4,6 +4,7 @@ using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using Umbraco.Core.Exceptions;
using Umbraco.Core.Scoping;
namespace Umbraco.Core.Mapping
{
@@ -42,12 +43,17 @@ namespace Umbraco.Core.Mapping
private readonly ConcurrentDictionary<Type, Dictionary<Type, Action<object, object, MapperContext>>> _maps
= new ConcurrentDictionary<Type, Dictionary<Type, Action<object, object, MapperContext>>>();
private readonly IScopeProvider _scopeProvider;
/// <summary>
/// Initializes a new instance of the <see cref="UmbracoMapper"/> class.
/// </summary>
/// <param name="profiles"></param>
public UmbracoMapper(MapDefinitionCollection profiles)
/// <param name="scopeProvider"></param>
public UmbracoMapper(MapDefinitionCollection profiles, IScopeProvider scopeProvider)
{
_scopeProvider = scopeProvider;
foreach (var profile in profiles)
profile.DefineMaps(this);
}
@@ -203,7 +209,10 @@ namespace Umbraco.Core.Mapping
if (ctor != null && map != null)
{
var target = ctor(source, context);
map(source, target, context);
using (var scope = _scopeProvider.CreateScope())
{
map(source, target, context);
}
return (TTarget)target;
}
@@ -248,11 +257,14 @@ namespace Umbraco.Core.Mapping
{
var targetList = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(targetGenericArg));
foreach (var sourceItem in source)
using (var scope = _scopeProvider.CreateScope())
{
var targetItem = ctor(sourceItem, context);
map(sourceItem, targetItem, context);
targetList.Add(targetItem);
foreach (var sourceItem in source)
{
var targetItem = ctor(sourceItem, context);
map(sourceItem, targetItem, context);
targetList.Add(targetItem);
}
}
object target = targetList;
@@ -292,8 +304,15 @@ namespace Umbraco.Core.Mapping
public TTarget Map<TSource, TTarget>(TSource source, TTarget target, Action<MapperContext> f)
{
var context = new MapperContext(this);
f(context);
return Map(source, target, context);
TTarget targetInstance;
using (var scope = _scopeProvider.CreateScope())
{
f(context);
targetInstance = Map(source, target, context);
}
return targetInstance;
}
/// <summary>
@@ -315,7 +334,10 @@ namespace Umbraco.Core.Mapping
// if there is a direct map, map
if (map != null)
{
map(source, target, context);
using (var scope = _scopeProvider.CreateScope())
{
map(source, target, context);
}
return target;
}

View File

@@ -1,17 +1,40 @@
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading;
using Moq;
using NUnit.Framework;
using Umbraco.Core.Events;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Scoping;
using Umbraco.Web.Models.ContentEditing;
using PropertyCollection = Umbraco.Core.Models.PropertyCollection;
namespace Umbraco.Tests.Mapping
{
[TestFixture]
public class MappingTests
{
private IScopeProvider _scopeProvider;
[SetUp]
public void MockScopeProvider()
{
var scopeMock = new Mock<IScopeProvider>();
scopeMock.Setup(x => x.CreateScope(
It.IsAny<IsolationLevel>(),
It.IsAny<RepositoryCacheMode>(),
It.IsAny<IEventDispatcher>(),
It.IsAny<bool?>(),
It.IsAny<bool>(),
It.IsAny<bool>()))
.Returns(Mock.Of<IScope>);
_scopeProvider = scopeMock.Object;
}
[Test]
public void SimpleMap()
{
@@ -19,7 +42,7 @@ namespace Umbraco.Tests.Mapping
{
new MapperDefinition1(),
});
var mapper = new UmbracoMapper(definitions);
var mapper = new UmbracoMapper(definitions, _scopeProvider);
var thing1 = new Thing1 { Value = "value" };
var thing2 = mapper.Map<Thing1, Thing2>(thing1);
@@ -44,7 +67,7 @@ namespace Umbraco.Tests.Mapping
{
new MapperDefinition1(),
});
var mapper = new UmbracoMapper(definitions);
var mapper = new UmbracoMapper(definitions, _scopeProvider);
var thing1A = new Thing1 { Value = "valueA" };
var thing1B = new Thing1 { Value = "valueB" };
@@ -78,7 +101,7 @@ namespace Umbraco.Tests.Mapping
{
new MapperDefinition1(),
});
var mapper = new UmbracoMapper(definitions);
var mapper = new UmbracoMapper(definitions, _scopeProvider);
var thing3 = new Thing3 { Value = "value" };
var thing2 = mapper.Map<Thing3, Thing2>(thing3);
@@ -103,7 +126,7 @@ namespace Umbraco.Tests.Mapping
{
new MapperDefinition2(),
});
var mapper = new UmbracoMapper(definitions);
var mapper = new UmbracoMapper(definitions, _scopeProvider);
// can map a PropertyCollection
var source = new PropertyCollection();
@@ -119,7 +142,7 @@ namespace Umbraco.Tests.Mapping
new MapperDefinition1(),
new MapperDefinition3(),
});
var mapper = new UmbracoMapper(definitions);
var mapper = new UmbracoMapper(definitions, _scopeProvider);
// the mapper currently has a map from Thing1 to Thing2
// because Thing3 inherits from Thing1, it will map a Thing3 instance,
@@ -179,7 +202,7 @@ namespace Umbraco.Tests.Mapping
{
new MapperDefinition4(),
});
var mapper = new UmbracoMapper(definitions);
var mapper = new UmbracoMapper(definitions, _scopeProvider);
var thing5 = new Thing5()
{
@@ -203,7 +226,7 @@ namespace Umbraco.Tests.Mapping
{
new MapperDefinition5(),
});
var mapper = new UmbracoMapper(definitions);
var mapper = new UmbracoMapper(definitions, _scopeProvider);
var thing7 = new Thing7();

View File

@@ -1,4 +1,5 @@
using System;
using System.Data;
using System.Globalization;
using System.Linq;
using System.Web.Security;
@@ -9,11 +10,13 @@ using Umbraco.Core.Cache;
using Umbraco.Core.Composing;
using Umbraco.Core.Configuration;
using Umbraco.Core.Dictionary;
using Umbraco.Core.Events;
using Umbraco.Core.Logging;
using Umbraco.Core.Mapping;
using Umbraco.Core.Models;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Persistence;
using Umbraco.Core.Scoping;
using Umbraco.Core.Services;
using Umbraco.Tests.TestHelpers;
using Umbraco.Tests.TestHelpers.Stubs;
@@ -98,10 +101,21 @@ namespace Umbraco.Tests.Testing.TestingTests
{
var umbracoContext = TestObjects.GetUmbracoContextMock();
var scopeProvider = new Mock<IScopeProvider>();
scopeProvider
.Setup(x => x.CreateScope(
It.IsAny<IsolationLevel>(),
It.IsAny<RepositoryCacheMode>(),
It.IsAny<IEventDispatcher>(),
It.IsAny<bool?>(),
It.IsAny<bool>(),
It.IsAny<bool>()))
.Returns(Mock.Of<IScope>);
var membershipHelper = new MembershipHelper(umbracoContext.HttpContext, Mock.Of<IPublishedMemberCache>(), Mock.Of<MembershipProvider>(), Mock.Of<RoleProvider>(), Mock.Of<IMemberService>(), Mock.Of<IMemberTypeService>(), Mock.Of<IUserService>(), Mock.Of<IPublicAccessService>(), Mock.Of<AppCaches>(), Mock.Of<ILogger>());
var umbracoHelper = new UmbracoHelper(Mock.Of<IPublishedContent>(), Mock.Of<ITagQuery>(), Mock.Of<ICultureDictionaryFactory>(), Mock.Of<IUmbracoComponentRenderer>(), Mock.Of<IPublishedContentQuery>(), membershipHelper);
var umbracoMapper = new UmbracoMapper(new MapDefinitionCollection(new[] { Mock.Of<IMapDefinition>() }));
var umbracoMapper = new UmbracoMapper(new MapDefinitionCollection(new[] { Mock.Of<IMapDefinition>() }), scopeProvider.Object);
// ReSharper disable once UnusedVariable
var umbracoApiController = new FakeUmbracoApiController(Mock.Of<IGlobalSettings>(), Mock.Of<IUmbracoContextAccessor>(), Mock.Of<ISqlContext>(), ServiceContext.CreatePartial(), AppCaches.NoCache, Mock.Of<IProfilingLogger>(), Mock.Of<IRuntimeState>(), umbracoHelper, umbracoMapper);