mirror of
https://github.com/OrchardCMS/Orchard.git
synced 2025-11-24 08:46:48 +08:00
@@ -73,6 +73,7 @@
|
||||
<Reference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.4.1.0\lib\net472\Microsoft.CodeDom.Providers.DotNetCompilerPlatform.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="Microsoft.Owin, Version=4.2.3.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Owin.4.2.3\lib\net45\Microsoft.Owin.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -82,8 +83,8 @@
|
||||
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="MySql.Data, Version=6.7.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MySql.Data.6.7.9\lib\net45\MySql.Data.dll</HintPath>
|
||||
<Reference Include="MySql.Data, Version=6.10.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\MySql.Data.6.10.9\lib\net452\MySql.Data.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
@@ -101,6 +102,8 @@
|
||||
<Reference Include="System.Buffers, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Buffers.4.6.1\lib\net462\System.Buffers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.ComponentModel" />
|
||||
<Reference Include="System.Configuration.Install" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.ComponentModel.DataAnnotations">
|
||||
<RequiredTargetFramework>3.5</RequiredTargetFramework>
|
||||
@@ -110,6 +113,9 @@
|
||||
<HintPath>..\..\lib\sqlce\System.Data.SqlServerCe.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Drawing.Design" />
|
||||
<Reference Include="System.Management" />
|
||||
<Reference Include="System.Memory, Version=4.0.5.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Memory.4.6.3\lib\net462\System.Memory.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -124,6 +130,7 @@
|
||||
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.4.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.6.3\lib\net462\System.Threading.Tasks.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Transactions" />
|
||||
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll</HintPath>
|
||||
</Reference>
|
||||
|
||||
@@ -208,12 +208,6 @@
|
||||
<compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008,40000,40008 /define:_MYTYPE=\"Web\" /optionInfer+" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=4.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
|
||||
</compilers>
|
||||
</system.codedom>
|
||||
<system.data>
|
||||
<DbProviderFactories>
|
||||
<remove invariant="MySql.Data.MySqlClient"/>
|
||||
<add name="MySQL Data Provider" invariant="MySql.Data.MySqlClient" description=".Net Framework Data Provider for MySQL" type="MySql.Data.MySqlClient.MySqlClientFactory, MySql.Data, Version=6.7.9.0, Culture=neutral, PublicKeyToken=c5687fc88969c44d"/>
|
||||
</DbProviderFactories>
|
||||
</system.data>
|
||||
<glimpse defaultRuntimePolicy="On" endpointBaseUri="~/Glimpse.axd">
|
||||
<logging level="Error" logLocation="App_data/Logs/Glimpse.log"/>
|
||||
<tabs>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<package id="Microsoft.Owin" version="4.2.3" targetFramework="net48" />
|
||||
<package id="Microsoft.Owin.Host.SystemWeb" version="4.2.3" targetFramework="net48" />
|
||||
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
|
||||
<package id="MySql.Data" version="6.7.9" targetFramework="net48" />
|
||||
<package id="MySql.Data" version="6.10.9" targetFramework="net48" />
|
||||
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net48" />
|
||||
<package id="Npgsql" version="4.0.17" targetFramework="net48" />
|
||||
<package id="Orchard.NuGet.Core" version="1.1.0.0" targetFramework="net48" />
|
||||
|
||||
@@ -5,9 +5,9 @@ using Orchard.Data.Migration.Schema;
|
||||
using Orchard.Environment;
|
||||
using Orchard.Environment.Configuration;
|
||||
using Orchard.Environment.Features;
|
||||
using Orchard.Exceptions;
|
||||
using Orchard.Logging;
|
||||
using Orchard.Tasks.Locking.Services;
|
||||
using Orchard.Exceptions;
|
||||
|
||||
namespace Orchard.Data.Migration {
|
||||
/// <summary>
|
||||
@@ -44,16 +44,21 @@ namespace Orchard.Data.Migration {
|
||||
public void Activated() {
|
||||
EnsureDistributedLockSchemaExists();
|
||||
|
||||
IDistributedLock @lock;
|
||||
if (_distributedLockService.TryAcquireLock(GetType().FullName, TimeSpan.FromMinutes(30), TimeSpan.FromMilliseconds(250), out @lock)) {
|
||||
if (_distributedLockService.TryAcquireLock(
|
||||
GetType().FullName,
|
||||
TimeSpan.FromMinutes(30),
|
||||
TimeSpan.FromMilliseconds(250),
|
||||
out IDistributedLock @lock)) {
|
||||
using (@lock) {
|
||||
// Let's make sure that the basic set of features is enabled. If there are any that are not enabled, then let's enable them first.
|
||||
// Let's make sure that the basic set of features is enabled.
|
||||
// If there are any that are not enabled, then let's enable them first.
|
||||
var theseFeaturesShouldAlwaysBeActive = new[] {
|
||||
"Common", "Containers", "Contents", "Dashboard", "Feeds", "Navigation", "Scheduling", "Settings", "Shapes", "Title"
|
||||
};
|
||||
|
||||
var enabledFeatures = _featureManager.GetEnabledFeatures().Select(f => f.Id).ToList();
|
||||
var featuresToEnable = theseFeaturesShouldAlwaysBeActive.Where(shouldBeActive => !enabledFeatures.Contains(shouldBeActive)).ToList();
|
||||
var featuresToEnable = theseFeaturesShouldAlwaysBeActive.Where(
|
||||
shouldBeActive => !enabledFeatures.Contains(shouldBeActive)).ToList();
|
||||
if (featuresToEnable.Any()) {
|
||||
_featureManager.EnableFeatures(featuresToEnable, true);
|
||||
}
|
||||
@@ -78,10 +83,10 @@ namespace Orchard.Data.Migration {
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This ensures that the framework migrations have run for the distributed locking feature, as existing Orchard installations will not have the required tables when upgrading.
|
||||
/// This ensures that the framework migrations have run for the distributed locking feature, as existing
|
||||
/// Orchard installations will not have the required tables when upgrading.
|
||||
/// </summary>
|
||||
private void EnsureDistributedLockSchemaExists()
|
||||
{
|
||||
private void EnsureDistributedLockSchemaExists() {
|
||||
// Ensure the distributed lock record schema exists.
|
||||
var schemaBuilder = new SchemaBuilder(_dataMigrationInterpreter);
|
||||
var distributedLockSchemaBuilder = new DistributedLockSchemaBuilder(_shellSettings, schemaBuilder);
|
||||
@@ -90,8 +95,6 @@ namespace Orchard.Data.Migration {
|
||||
// Workaround to avoid some Transaction issue for PostgreSQL.
|
||||
if (_shellSettings.DataProvider.Equals("PostgreSql", StringComparison.OrdinalIgnoreCase)) {
|
||||
_transactionManager.RequireNew();
|
||||
distributedLockSchemaBuilder.CreateSchema();
|
||||
return;
|
||||
}
|
||||
|
||||
distributedLockSchemaBuilder.CreateSchema();
|
||||
|
||||
@@ -97,9 +97,9 @@ namespace Orchard.Data.Migration.Interpreters {
|
||||
|
||||
if (columnList.Count > 1) {
|
||||
sqlCommand.CommandText = $@"
|
||||
SELECT SUM(CHARACTER_MAXIMUM_LENGTH)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE table_name = '{tableName}'
|
||||
SELECT SUM(CHARACTER_MAXIMUM_LENGTH)
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE table_name = '{tableName}'
|
||||
AND COLUMN_NAME in ({columnNames})
|
||||
AND TABLE_SCHEMA = '{session.Connection.Database}'
|
||||
AND (Data_type = 'varchar');";
|
||||
@@ -117,9 +117,9 @@ namespace Orchard.Data.Migration.Interpreters {
|
||||
}
|
||||
// Check whether the index contains big nvarchar columns or text fields.
|
||||
sqlCommand.CommandText = $@"
|
||||
SELECT COLUMN_NAME
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE table_name = '{tableName}'
|
||||
SELECT COLUMN_NAME
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE table_name = '{tableName}'
|
||||
AND COLUMN_NAME in ({columnNames})
|
||||
AND TABLE_SCHEMA = '{session.Connection.Database}'
|
||||
AND ((Data_type = 'varchar' and CHARACTER_MAXIMUM_LENGTH > {indexMaximumLength}) OR data_type= 'text');";
|
||||
|
||||
@@ -9,9 +9,9 @@ using Orchard.Environment.Configuration;
|
||||
|
||||
namespace Orchard.Data {
|
||||
public class NoLockInterceptor : EmptyInterceptor, ISessionInterceptor {
|
||||
|
||||
private readonly ShellSettings _shellSettings;
|
||||
private readonly IEnumerable<INoLockTableProvider> _noLockTableProviders;
|
||||
private readonly bool _supportsNoLock;
|
||||
|
||||
public NoLockInterceptor(
|
||||
ShellSettings shellSettings,
|
||||
@@ -19,6 +19,10 @@ namespace Orchard.Data {
|
||||
|
||||
_shellSettings = shellSettings;
|
||||
_noLockTableProviders = noLockTableProviders;
|
||||
|
||||
// Only SQL Server supports NOLOCK.
|
||||
var provider = _shellSettings?.DataProvider?.ToLower();
|
||||
_supportsNoLock = provider == "sqlserver" || provider == "sqlce";
|
||||
}
|
||||
|
||||
private List<string> _tableNames;
|
||||
@@ -27,7 +31,7 @@ namespace Orchard.Data {
|
||||
if (_tableNames == null) {
|
||||
_tableNames = new List<string>(
|
||||
_noLockTableProviders
|
||||
.SelectMany(nltp => nltp.GetTableNames())
|
||||
.SelectMany(providers => providers.GetTableNames())
|
||||
.Distinct(StringComparer.OrdinalIgnoreCase)
|
||||
.Select(n => GetPrefixedTableName(n.Trim())));
|
||||
}
|
||||
@@ -45,6 +49,11 @@ namespace Orchard.Data {
|
||||
|
||||
// based on https://stackoverflow.com/a/39518098/2669614
|
||||
public override SqlString OnPrepareStatement(SqlString sql) {
|
||||
// Skip entirely for providers that do not support NOLOCK
|
||||
if (!_supportsNoLock) {
|
||||
return sql;
|
||||
}
|
||||
|
||||
// only work on select queries
|
||||
if (sql.StartsWithCaseInsensitive("select")) {
|
||||
// see whether we have anything to add the NOLOCK hint to
|
||||
@@ -66,7 +75,7 @@ namespace Orchard.Data {
|
||||
// The captured strings in this group are ordered with respect to where they are
|
||||
// found in the original string: that means that each string may be contained
|
||||
// in any, all or none of the following ones in the array. When a captured string
|
||||
// is part of another, it is so in its entirety, meaning there cannote be a case
|
||||
// is part of another, it is so in its entirety, meaning there cannot be a case
|
||||
// when two captured strings intersect partially.
|
||||
// Take for example the following query:
|
||||
//
|
||||
@@ -148,10 +157,11 @@ namespace Orchard.Data {
|
||||
// starting from the end.
|
||||
var oFromEnd = outer.OriginalEnd - inner.OriginalIndex;
|
||||
insertionIndex = outer.Value.Length - oFromEnd;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// outer is still the same as what we captured originally
|
||||
// we are changing it here for the first time.
|
||||
// This means the index of our ssubstring within it has not changed
|
||||
// This means the index of our substring within it has not changed
|
||||
}
|
||||
outer.Value = outer.Value
|
||||
// Remove old substring
|
||||
@@ -231,7 +241,7 @@ namespace Orchard.Data {
|
||||
if (tableItem != null) {
|
||||
// the table is involved in this statement
|
||||
var tableIndex = parts.IndexOf(tableItem);
|
||||
// recompute whereIndex in case we added stuff to parts
|
||||
// re-compute whereIndex in case we added stuff to parts
|
||||
whereIndex = whereItem != null ? parts.IndexOf(whereItem) : parts.Count;
|
||||
if (tableIndex > fromIndex && tableIndex < whereIndex) { // sanity check
|
||||
// if before the table name we have "," or "FROM", this is not a join, but rather
|
||||
@@ -243,11 +253,13 @@ namespace Orchard.Data {
|
||||
if (parts[tableIndex + 1].Equals("where", StringComparison.OrdinalIgnoreCase)) {
|
||||
// There is no alias in the query, so we add "WITH(NOLOCK)" immediately after table name but before the "where" clause.
|
||||
parts.Insert(tableIndex + 1, "WITH(NOLOCK)");
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// We add "WITH(NOLOCK)" after the table alias.
|
||||
parts.Insert(tableIndex + 2, "WITH(NOLOCK)");
|
||||
}
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
// probably doing a join, so edit the next "on" and make it
|
||||
// "WITH (NOLOCK) on"
|
||||
for (int i = tableIndex + 1; i < whereIndex; i++) {
|
||||
@@ -271,6 +283,5 @@ namespace Orchard.Data {
|
||||
return query;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,20 +16,30 @@ namespace Orchard.Tasks.Locking.Services {
|
||||
public void CreateSchema() {
|
||||
_schemaBuilder.CreateTable(TableName, table => table
|
||||
.Column<int>("Id", column => column.PrimaryKey().Identity())
|
||||
.Column<string>("Name", column => column.NotNull().WithLength(512).Unique())
|
||||
// Keep 512 chars but avoid inline .Unique() to prevent MySQL TEXT/BLOB key-length errors.
|
||||
.Column<string>("Name", column => column.NotNull().WithLength(512))
|
||||
.Column<string>("MachineName", column => column.WithLength(256))
|
||||
.Column<DateTime>("CreatedUtc")
|
||||
.Column<DateTime>("ValidUntilUtc", column => column.Nullable()));
|
||||
|
||||
// MySQL-specific adjustment to avoid error when adding the unique constraint.
|
||||
if (string.Equals(_shellSettings.DataProvider, "MySql", StringComparison.OrdinalIgnoreCase)) {
|
||||
// Force VARCHAR(512) on MySQL (some interpreters map >255 to TEXT).
|
||||
_schemaBuilder.ExecuteSql(
|
||||
$"ALTER TABLE {_schemaBuilder.TableDbName(TableName)} MODIFY COLUMN Name VARCHAR(512) NOT NULL;",
|
||||
cmd => cmd.ForProvider("MySql"));
|
||||
}
|
||||
|
||||
_schemaBuilder.AlterTable(TableName, table => {
|
||||
table.AddUniqueConstraint("UQ_DistributedLockRecord_Name", "Name");
|
||||
table.CreateIndex("IDX_DistributedLockRecord_Name", "Name");
|
||||
});
|
||||
}
|
||||
|
||||
public bool SchemaExists() {
|
||||
try {
|
||||
var tablePrefix = String.IsNullOrEmpty(_shellSettings.DataTablePrefix) ? "" : _shellSettings.DataTablePrefix + "_";
|
||||
_schemaBuilder.ExecuteSql(String.Format("select * from {0}{1}", tablePrefix, TableName));
|
||||
_schemaBuilder.ExecuteSql($"select 1 from {_schemaBuilder.TableDbName(TableName)}");
|
||||
|
||||
return true;
|
||||
}
|
||||
catch {
|
||||
|
||||
Reference in New Issue
Block a user