U4-9201 - fix it all
This commit is contained in:
@@ -94,13 +94,13 @@ namespace Umbraco.Core
|
||||
public ISqlSyntaxProvider SqlSyntax { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="Database"/> object for doing CRUD operations against custom tables that resides in the Umbraco database.
|
||||
/// Gets an "ambient" database for doing CRUD operations against custom tables that resides in the Umbraco database.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Should not be used for operation against standard Umbraco tables; as services should be used instead.</para>
|
||||
/// <para>Gets or creates an "ambient" database that is either stored in http context + available for the whole
|
||||
/// request + auto-disposed at the end of the request, or in call context if there is no http context - in which
|
||||
/// case it needs to be explicitely disposed so it is removed from call context.</para>
|
||||
/// request + auto-disposed at the end of the request, or stored in call context if there is no http context - in which
|
||||
/// case it *must* be explicitely disposed (which will remove it from call context).</para>
|
||||
/// </remarks>
|
||||
public virtual UmbracoDatabase Database
|
||||
{
|
||||
@@ -108,24 +108,32 @@ namespace Umbraco.Core
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the "ambient" database (if any) and installs a new <see cref="Database"/> object.
|
||||
/// Replaces the "ambient" database (if any) and by a new temp database.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The returned IDisposable *must* be diposed in order to properly disposed the safe database and
|
||||
/// <para>The returned IDisposable *must* be diposed in order to properly dispose the temp database and
|
||||
/// restore the original "ambient" database (if any).</para>
|
||||
/// <para>This is to be used in background tasks to ensure that they have an "ambient" database which
|
||||
/// will be properly removed from call context and does not interfere with anything else. In most case
|
||||
/// it is not replacing anything, just temporarily installing a database in context.</para>
|
||||
/// </remarks>
|
||||
public virtual IDisposable UsingSafeDatabase
|
||||
public virtual IDisposable UseSafeDatabase(bool force = false)
|
||||
{
|
||||
get
|
||||
var factory = _factory as DefaultDatabaseFactory;
|
||||
if (factory == null) throw new NotSupportedException();
|
||||
if (DefaultDatabaseFactory.HasAmbientDatabase)
|
||||
{
|
||||
var factory = _factory as DefaultDatabaseFactory;
|
||||
if (factory == null) throw new NotSupportedException();
|
||||
var database = factory.CreateDatabaseInstance(DefaultDatabaseFactory.ContextOwner.None);
|
||||
return new UsedDatabase(database, _logger);
|
||||
// has ambient,
|
||||
// if forcing, detach it and replace it with a new, temp, database
|
||||
// when the UsingDatabase is disposed, the temp database is disposed and the original one is re-instated
|
||||
// else do nothing (and nothing will be disposed)
|
||||
return force
|
||||
? new UsingDatabase(DefaultDatabaseFactory.DetachAmbientDatabase(), factory.CreateDatabase())
|
||||
: new UsingDatabase(null, null);
|
||||
}
|
||||
|
||||
// create a new, temp, database (will be disposed with UsingDatabase)
|
||||
return new UsingDatabase(null, factory.CreateDatabase());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -788,30 +796,26 @@ namespace Umbraco.Core
|
||||
return true;
|
||||
}
|
||||
|
||||
private class UsedDatabase : IDisposable
|
||||
private class UsingDatabase : IDisposable
|
||||
{
|
||||
private readonly UmbracoDatabase _database;
|
||||
private readonly ILogger _logger;
|
||||
private readonly UmbracoDatabase _orig;
|
||||
private readonly UmbracoDatabase _temp;
|
||||
|
||||
public UsedDatabase(UmbracoDatabase database, ILogger logger)
|
||||
public UsingDatabase(UmbracoDatabase orig, UmbracoDatabase temp)
|
||||
{
|
||||
_logger = logger;
|
||||
|
||||
// replace with ours
|
||||
_database = DefaultDatabaseFactory.DetachDatabase();
|
||||
_logger.Debug<DatabaseContext>("Detached db " + (_database == null ? "x" : _database.InstanceSid) + ".");
|
||||
DefaultDatabaseFactory.AttachDatabase(database);
|
||||
_logger.Debug<DatabaseContext>("Attached db " + database.InstanceSid + ".");
|
||||
_orig = orig;
|
||||
_temp = temp;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
// restore the original DB
|
||||
var db = DefaultDatabaseFactory.DetachDatabase();
|
||||
_logger.Debug<DatabaseContext>("Detached db " + db.InstanceSid + ".");
|
||||
db.Dispose();
|
||||
DefaultDatabaseFactory.AttachDatabase(_database);
|
||||
_logger.Debug<DatabaseContext>("Attached db " + (_database == null ? "x" : _database.InstanceSid) + ".");
|
||||
if (_temp != null)
|
||||
{
|
||||
_temp.Dispose();
|
||||
if (_orig != null)
|
||||
DefaultDatabaseFactory.AttachAmbientDatabase(_orig);
|
||||
}
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Remoting.Messaging;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Logging;
|
||||
@@ -250,12 +251,23 @@ namespace Umbraco.Core.Persistence
|
||||
|
||||
static DefaultDatabaseFactory()
|
||||
{
|
||||
SafeCallContext.Register(DetachDatabase, AttachDatabase);
|
||||
SafeCallContext.Register(DetachAmbientDatabase, AttachAmbientDatabase);
|
||||
}
|
||||
|
||||
// gets a value indicating whether there is an ambient database
|
||||
internal static bool HasAmbientDatabase
|
||||
{
|
||||
get
|
||||
{
|
||||
return HttpContext.Current == null
|
||||
? NonContextValue != null
|
||||
: HttpContext.Current.Items[typeof (DefaultDatabaseFactory)] != null;
|
||||
}
|
||||
}
|
||||
|
||||
// detaches the current database
|
||||
// ie returns the database and remove it from whatever is "context"
|
||||
internal static UmbracoDatabase DetachDatabase()
|
||||
internal static UmbracoDatabase DetachAmbientDatabase()
|
||||
{
|
||||
UmbracoDatabase database;
|
||||
|
||||
@@ -277,7 +289,7 @@ namespace Umbraco.Core.Persistence
|
||||
// attach a current database
|
||||
// ie assign it to whatever is "context"
|
||||
// throws if there already is a database
|
||||
internal static void AttachDatabase(object o)
|
||||
internal static void AttachAmbientDatabase(object o)
|
||||
{
|
||||
var database = o as UmbracoDatabase;
|
||||
if (o != null && database == null) throw new ArgumentException("Not an UmbracoDatabase.", "o");
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<DefineConstants>TRACE;DEBUG;DEBUG_DATABASES</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<Prefer32Bit>false</Prefer32Bit>
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Umbraco.Web.Scheduling
|
||||
}
|
||||
|
||||
// running on a background task, requires a safe database (see UsingSafeDatabase doc)
|
||||
using (ApplicationContext.Current.DatabaseContext.UsingSafeDatabase)
|
||||
using (ApplicationContext.Current.DatabaseContext.UseSafeDatabase(true))
|
||||
using (DisposableTimer.DebugDuration<LogScrubber>("Log scrubbing executing", "Log scrubbing complete"))
|
||||
{
|
||||
Log.CleanLogs(GetLogScrubbingMaximumAge(_settings));
|
||||
|
||||
@@ -83,10 +83,8 @@ namespace Umbraco.Web.Scheduling
|
||||
};
|
||||
|
||||
// running on a background task, requires a safe database (see UsingSafeDatabase doc)
|
||||
//
|
||||
// this is because GetAuthenticationHeaderValue uses UserService to load the current user, hence requires a database
|
||||
//
|
||||
using (ApplicationContext.Current.DatabaseContext.UsingSafeDatabase)
|
||||
// (GetAuthenticationHeaderValue uses UserService to load the current user, hence requires a database)
|
||||
using (ApplicationContext.Current.DatabaseContext.UseSafeDatabase(true))
|
||||
{
|
||||
//pass custom the authorization header
|
||||
request.Headers.Authorization = AdminTokenAuthorizeAttribute.GetAuthenticationHeaderValue(_appContext);
|
||||
|
||||
@@ -138,7 +138,7 @@ namespace Umbraco.Web.Strategies
|
||||
try
|
||||
{
|
||||
// running on a background task, requires a safe database (see UsingSafeDatabase doc)
|
||||
using (ApplicationContext.Current.DatabaseContext.UsingSafeDatabase)
|
||||
using (ApplicationContext.Current.DatabaseContext.UseSafeDatabase(true))
|
||||
{
|
||||
_svc.TouchServer(_serverAddress, _svc.CurrentServerIdentity, _registrar.Options.StaleServerTimeout);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ namespace UmbracoExamine.DataServices
|
||||
{
|
||||
public class UmbracoContentService : IContentService
|
||||
{
|
||||
|
||||
private readonly ApplicationContext _applicationContext;
|
||||
|
||||
public UmbracoContentService()
|
||||
@@ -58,7 +57,7 @@ namespace UmbracoExamine.DataServices
|
||||
[Obsolete("This should no longer be used, latest content will be indexed by using the IContentService directly")]
|
||||
public XDocument GetLatestContentByXPath(string xpath)
|
||||
{
|
||||
using (_applicationContext.DatabaseContext.UsingSafeDatabase)
|
||||
using (_applicationContext.DatabaseContext.UseSafeDatabase()) // reuse current db if any else use & dispose one
|
||||
{
|
||||
var xmlContent = XDocument.Parse("<content></content>");
|
||||
var rootContent = _applicationContext.Services.ContentService.GetRootContent();
|
||||
@@ -80,7 +79,7 @@ namespace UmbracoExamine.DataServices
|
||||
/// <returns></returns>
|
||||
public bool IsProtected(int nodeId, string path)
|
||||
{
|
||||
using (_applicationContext.DatabaseContext.UsingSafeDatabase)
|
||||
using (_applicationContext.DatabaseContext.UseSafeDatabase()) // reuse current db if any else use & dispose one
|
||||
{
|
||||
return _applicationContext.Services.PublicAccessService.IsProtected(path.EnsureEndsWith("," + nodeId));
|
||||
}
|
||||
@@ -93,8 +92,8 @@ namespace UmbracoExamine.DataServices
|
||||
|
||||
public IEnumerable<string> GetAllUserPropertyNames()
|
||||
{
|
||||
using (_applicationContext.DatabaseContext.UsingSafeDatabase)
|
||||
{
|
||||
using (_applicationContext.DatabaseContext.UseSafeDatabase()) // reuse current db if any else use & dispose one
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = _applicationContext.DatabaseContext.Database.Fetch<string>("select distinct alias from cmsPropertyType order by alias");
|
||||
|
||||
Reference in New Issue
Block a user