diff --git a/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs b/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs index 2623677e43..9061be62e4 100644 --- a/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs +++ b/src/Umbraco.Core/Persistence/Repositories/RepositoryBase.cs @@ -125,19 +125,35 @@ namespace Umbraco.Core.Persistence.Repositories return provider.GetOrCreateCache(); } - private static RepositoryCachePolicyOptions _defaultOptions; + // this is a *bad* idea because PerformCount captures the current repository and its UOW + // + //private static RepositoryCachePolicyOptions _defaultOptions; + //protected virtual RepositoryCachePolicyOptions DefaultOptions + //{ + // get + // { + // return _defaultOptions ?? (_defaultOptions + // = new RepositoryCachePolicyOptions(() => + // { + // // get count of all entities of current type (TEntity) to ensure cached result is correct + // // create query once if it is needed (no need for locking here) - query is static! + // var query = _hasIdQuery ?? (_hasIdQuery = Query.Builder.Where(x => x.Id != 0)); + // return PerformCount(query); + // })); + // } + //} + protected virtual RepositoryCachePolicyOptions DefaultOptions { get { - return _defaultOptions ?? (_defaultOptions - = new RepositoryCachePolicyOptions(() => + return new RepositoryCachePolicyOptions(() => { // get count of all entities of current type (TEntity) to ensure cached result is correct // create query once if it is needed (no need for locking here) - query is static! var query = _hasIdQuery ?? (_hasIdQuery = Query.Builder.Where(x => x.Id != 0)); return PerformCount(query); - })); + }); } } diff --git a/src/Umbraco.Core/Persistence/UnitOfWork/ScopeUnitOfWork.cs b/src/Umbraco.Core/Persistence/UnitOfWork/ScopeUnitOfWork.cs index 35d5ad80c7..1e6ae7f5b4 100644 --- a/src/Umbraco.Core/Persistence/UnitOfWork/ScopeUnitOfWork.cs +++ b/src/Umbraco.Core/Persistence/UnitOfWork/ScopeUnitOfWork.cs @@ -154,6 +154,9 @@ namespace Umbraco.Core.Persistence.UnitOfWork public IScope Scope { + // TODO + // once we are absolutely sure that our UOW cannot be disposed more than once, + // this should throw if the UOW has already been disposed, NOT recreate a scope! get { return _scope ?? (_scope = _scopeProvider.CreateScope(_isolationLevel)); } } diff --git a/src/Umbraco.Core/PluginManager.cs b/src/Umbraco.Core/PluginManager.cs index 102f0ee88f..af4a597ea3 100644 --- a/src/Umbraco.Core/PluginManager.cs +++ b/src/Umbraco.Core/PluginManager.cs @@ -420,18 +420,31 @@ namespace Umbraco.Core internal void UpdateCachedPluginsFile(IEnumerable typesFound, TypeResolutionKind resolutionType) { var filePath = GetPluginListFilePath(); - XDocument xml; - try + XDocument xml = null; + + if (File.Exists(filePath)) { - xml = XDocument.Load(filePath); - } - catch - { - //if there's an exception loading then this is somehow corrupt, we'll just replace it. - File.Delete(filePath); - //create the document and the root - xml = new XDocument(new XElement("plugins")); + try + { + xml = XDocument.Load(filePath); + } + catch + { + try + { + File.Delete(filePath); // file is corrupt somehow + } + catch + { + // on-purpose, does not matter + } + xml = null; + } } + + // else replace the xml, create the document and the root + if (xml == null) xml = new XDocument(new XElement("plugins")); + if (xml.Root == null) { //if for some reason there is no root, create it @@ -458,6 +471,9 @@ namespace Umbraco.Core //now we have the type element, we need to clear any previous types as children and add/update it with new ones typeElement.ReplaceNodes(typesFound.Select(x => new XElement("add", new XAttribute("type", x.AssemblyQualifiedName)))); //save the xml file + var dir = Path.GetDirectoryName(filePath); + if (Directory.Exists(dir) == false) + Directory.CreateDirectory(dir); xml.Save(filePath); } diff --git a/src/Umbraco.Core/Scoping/ScopeProvider.cs b/src/Umbraco.Core/Scoping/ScopeProvider.cs index 0992d4cb17..cf34dc8821 100644 --- a/src/Umbraco.Core/Scoping/ScopeProvider.cs +++ b/src/Umbraco.Core/Scoping/ScopeProvider.cs @@ -33,7 +33,17 @@ namespace Umbraco.Core.Scoping o => { // cannot re-attached over leaked scope/context - if (StaticAmbientScope != null) throw new Exception("Found leaked scope when restoring call context."); + // except of course over NoScope (which leaks) + var ambientScope = StaticAmbientScope; + if (ambientScope != null) + { + var ambientNoScope = ambientScope as NoScope; + if (ambientNoScope == null) + throw new Exception("Found leaked scope when restoring call context."); + + // this should rollback any pending transaction + ambientNoScope.Dispose(); + } if (StaticAmbientContext != null) throw new Exception("Found leaked context when restoring call context."); var t = (Tuple)o;