Skip to content

Commit 64eafbc

Browse files
committed
Merge branch 'issue/8684' into issue/8686-dev
2 parents 8248460 + 01b3f24 commit 64eafbc

File tree

22 files changed

+280
-81
lines changed

22 files changed

+280
-81
lines changed

Diff for: src/Orchard.Specs/Hosting/Orchard.Web/Web.config

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@
5353
<add extension=".csproj" type="Orchard.Environment.Extensions.Compilers.CSharpExtensionBuildProviderShim"/>
5454
</buildProviders>
5555
<assemblies>
56-
<add assembly="Microsoft.Owin.Host.SystemWeb, Version=4.1.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
56+
<add assembly="Microsoft.Owin.Host.SystemWeb, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
5757
<add assembly="System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
58-
<add assembly="System.Web.Mvc, Version=5.2.7, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
58+
<add assembly="System.Web.Mvc, Version=5.2.7, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
5959
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
6060
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL" />
6161
<add assembly="System.Data.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />

Diff for: src/Orchard.Web/Core/Common/Migrations.cs

+109-29
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,30 @@
11
using System;
2+
using System.Collections.Generic;
3+
using System.Data;
24
using System.Linq;
35
using Orchard.ContentManagement.MetaData;
46
using Orchard.Core.Common.Models;
57
using Orchard.Core.Contents.Extensions;
68
using Orchard.Data;
79
using Orchard.Data.Migration;
10+
using Orchard.Environment.Configuration;
811

912
namespace Orchard.Core.Common {
1013
public class Migrations : DataMigrationImpl {
1114
private readonly IRepository<IdentityPartRecord> _identityPartRepository;
15+
private readonly ISessionFactoryHolder _sessionFactoryHolder;
16+
private readonly ShellSettings _shellSettings;
1217

18+
private HashSet<string> _existingIndexNames = new HashSet<string>();
1319

14-
public Migrations(IRepository<IdentityPartRecord> identityPartRepository) {
20+
21+
public Migrations(
22+
IRepository<IdentityPartRecord> identityPartRepository,
23+
ISessionFactoryHolder sessionFactoryHolder,
24+
ShellSettings shellSettings) {
1525
_identityPartRepository = identityPartRepository;
26+
_sessionFactoryHolder = sessionFactoryHolder;
27+
_shellSettings = shellSettings;
1628
}
1729

1830

@@ -155,35 +167,72 @@ public int UpdateFrom5() {
155167
return 6;
156168
}
157169

170+
// When upgrading from version 6 of 1.10.x (up until version 9), we'll just execute the same steps, but in a
171+
// different order.
158172
public int UpdateFrom6() {
159-
SchemaBuilder.AlterTable(nameof(IdentityPartRecord), table => table
160-
.CreateIndex($"IDX_{nameof(IdentityPartRecord)}_{nameof(IdentityPartRecord.Identifier)}", nameof(IdentityPartRecord.Identifier)));
173+
// This is the original step of the dev branch.
174+
AddIndexForIdentityPartRecordIdentifier();
161175

162176
return 7;
163177
}
164178

165179
public int UpdateFrom7() {
166-
// The Container_Id is basically a foreign key, used in several queries
167-
SchemaBuilder.AlterTable(nameof(CommonPartRecord), table => {
168-
table.CreateIndex($"IDX_{nameof(CommonPartRecord)}_Container_id",
169-
"Container_id");
170-
});
180+
// This is the original step of the dev branch.
181+
AddIndexForCommonPartRecordContainerId();
182+
183+
// When upgrading from version 7 of 1.10.x, this index isn't created yet, so we need to run this step
184+
// "again". On the other hand, AddIndexesForCommonPartOwner in UpdateFrom8 won't do anything, because those
185+
// indexes were added in the 1.10.x version of UpdateFrom6.
186+
AddIndexForIdentityPartRecordIdentifier();
171187

172188
return 8;
173189
}
174190

175191
public int UpdateFrom8() {
176-
// Studying SQL Server query execution plans we noticed that when the system
177-
// tries to find content items for requests such as
178-
// "The items of type TTT owned by me, ordered from the most recent"
179-
// the existing indexes are not used. SQL Server does an index scan on the
180-
// Primary key for CommonPartRecord. This may lead to annoying deadlocks when
181-
// there are two concurrent transactions that are doing both this kind of query
182-
// as well as an update (or insert) in the CommonPartRecord.
183-
// Tests show that this can be easily fixed by adding a non-clustered index
184-
// with these keys: OwnerId, {one of PublishedUTC, ModifiedUTC, CreatedUTC}.
185-
// That means we need three indexes (one for each DateTime) to support ordering
186-
// on either of them.
192+
// This is the original step of the dev branch.
193+
AddIndexesForCommonPartOwner();
194+
195+
// When upgrading from version 8 of 1.10.x, this index isn't created yet, so we need to run this step
196+
// "again"
197+
AddIndexForCommonPartRecordContainerId();
198+
199+
return 9;
200+
}
201+
202+
// This change was originally UpdateFrom7 on 1.10.x and UpdateFrom6 on dev.
203+
private void AddIndexForIdentityPartRecordIdentifier() {
204+
var indexName = $"IDX_{nameof(IdentityPartRecord)}_{nameof(IdentityPartRecord.Identifier)}";
205+
206+
if (IndexExists(nameof(IdentityPartRecord), indexName)) return;
207+
208+
SchemaBuilder.AlterTable(nameof(IdentityPartRecord), table => table.CreateIndex(
209+
indexName,
210+
nameof(IdentityPartRecord.Identifier)));
211+
212+
IndexCreated(nameof(IdentityPartRecord), indexName);
213+
}
214+
215+
// This change was originally UpdateFrom8 on 1.10.x and UpdateFrom7 on dev.
216+
private void AddIndexForCommonPartRecordContainerId() {
217+
var indexName = $"IDX_{nameof(CommonPartRecord)}_Container_id";
218+
219+
if (IndexExists(nameof(CommonPartRecord), indexName)) return;
220+
221+
// Container_Id is used in several queries like a foreign key.
222+
SchemaBuilder.AlterTable(nameof(CommonPartRecord), table => table.CreateIndex(indexName, "Container_id"));
223+
224+
IndexCreated(nameof(CommonPartRecord), indexName);
225+
}
226+
227+
// This change was originally UpdateFrom6 on 1.10.x and UpdateFrom8 on dev.
228+
private void AddIndexesForCommonPartOwner() {
229+
// Studying SQL Server query execution plans we noticed that when the system tries to find content items for
230+
// requests such as "The items of type TTT owned by me, ordered from the most recent" the existing indexes
231+
// are not used. SQL Server does an index scan on the Primary key for CommonPartRecord. This may lead to
232+
// annoying deadlocks when there are two concurrent transactions that are doing both this kind of query as
233+
// well as an update (or insert) in the CommonPartRecord. Tests show that this can be easily fixed by adding
234+
// a non-clustered index with these keys: OwnerId, {one of PublishedUTC, ModifiedUTC, CreatedUTC}. That
235+
// means we need three indexes (one for each DateTime) to support ordering on either of them.
187236

188237
// The queries we analyzed look like (in pseudo sql)
189238
// SELECT TOP (N) *
@@ -198,20 +247,51 @@ public int UpdateFrom8() {
198247
// and this_.Published = 1
199248
// ORDER BY
200249
// commonpart2_PublishedUtc desc
250+
var createdUtcIndexName = $"IDX_{nameof(CommonPartRecord)}_OwnedBy_ByCreation";
251+
var modifiedUtcIndexName = $"IDX_{nameof(CommonPartRecord)}_OwnedBy_ByModification";
252+
var publishedUtcIndexName = $"IDX_{nameof(CommonPartRecord)}_OwnedBy_ByPublication";
253+
254+
if (IndexExists(nameof(CommonPartRecord), createdUtcIndexName)) return;
201255

202256
SchemaBuilder.AlterTable(nameof(CommonPartRecord), table => {
203-
table.CreateIndex($"IDX_{nameof(CommonPartRecord)}_OwnedBy_ByCreation",
204-
nameof(CommonPartRecord.OwnerId),
205-
nameof(CommonPartRecord.CreatedUtc));
206-
table.CreateIndex($"IDX_{nameof(CommonPartRecord)}_OwnedBy_ByModification",
207-
nameof(CommonPartRecord.OwnerId),
208-
nameof(CommonPartRecord.ModifiedUtc));
209-
table.CreateIndex($"IDX_{nameof(CommonPartRecord)}_OwnedBy_ByPublication",
210-
nameof(CommonPartRecord.OwnerId),
211-
nameof(CommonPartRecord.PublishedUtc));
257+
table.CreateIndex(createdUtcIndexName, nameof(CommonPartRecord.OwnerId), nameof(CommonPartRecord.CreatedUtc));
258+
table.CreateIndex(modifiedUtcIndexName, nameof(CommonPartRecord.OwnerId), nameof(CommonPartRecord.ModifiedUtc));
259+
table.CreateIndex(publishedUtcIndexName, nameof(CommonPartRecord.OwnerId), nameof(CommonPartRecord.PublishedUtc));
212260
});
213261

214-
return 9;
262+
IndexCreated(nameof(CommonPartRecord), createdUtcIndexName);
263+
IndexCreated(nameof(CommonPartRecord), modifiedUtcIndexName);
264+
IndexCreated(nameof(CommonPartRecord), publishedUtcIndexName);
265+
}
266+
267+
private bool IndexExists(string tableName, string indexName) {
268+
var tenantTablesPrefix = string.IsNullOrEmpty(_shellSettings.DataTablePrefix)
269+
? string.Empty : $"{_shellSettings.DataTablePrefix}_";
270+
271+
if (!_existingIndexNames.Any()) {
272+
// Database-agnostic way of checking the existence of an index.
273+
using (var session = _sessionFactoryHolder.GetSessionFactory().OpenSession()) {
274+
var connection = session.Connection ?? throw new InvalidOperationException(
275+
"The database connection object should derive from DbConnection to check if an index exists.");
276+
277+
var indexes = connection.GetSchema("Indexes").Rows.Cast<DataRow>();
278+
279+
if (!string.IsNullOrEmpty(tenantTablesPrefix)) {
280+
indexes = indexes.Where(row => row["TABLE_NAME"].ToString().StartsWith(tenantTablesPrefix));
281+
}
282+
283+
_existingIndexNames = indexes.Select(row => $"{row["TABLE_NAME"]}.{row["INDEX_NAME"]}").ToHashSet();
284+
}
285+
}
286+
287+
return _existingIndexNames.Contains($"{SchemaBuilder.TableDbName(tableName)}.{tenantTablesPrefix}{indexName}");
288+
}
289+
290+
private void IndexCreated(string tableName, string indexName) {
291+
var tenantTablesPrefix = string.IsNullOrEmpty(_shellSettings.DataTablePrefix)
292+
? string.Empty : $"{_shellSettings.DataTablePrefix}_";
293+
294+
_existingIndexNames.Add($"{SchemaBuilder.TableDbName(tableName)}.{tenantTablesPrefix}{indexName}");
215295
}
216296
}
217297
}

Diff for: src/Orchard.Web/Core/Orchard.Core.csproj

+4
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,14 @@
6363
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
6464
<HintPath>..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>
6565
</Reference>
66+
<Reference Include="NHibernate, Version=5.3.0.0, Culture=neutral, PublicKeyToken=aa95f207798dfdb4, processorArchitecture=MSIL">
67+
<HintPath>..\..\packages\NHibernate.5.3.10\lib\net461\NHibernate.dll</HintPath>
68+
</Reference>
6669
<Reference Include="System" />
6770
<Reference Include="System.ComponentModel.DataAnnotations">
6871
<RequiredTargetFramework>3.5</RequiredTargetFramework>
6972
</Reference>
73+
<Reference Include="System.Data" />
7074
<Reference Include="System.Data.DataSetExtensions" />
7175
<Reference Include="System.Web" />
7276
<Reference Include="System.Web.ApplicationServices" />

Diff for: src/Orchard.Web/Core/packages.config

+1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@
55
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
66
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net48" />
77
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
8+
<package id="NHibernate" version="5.3.10" targetFramework="net48" />
89
</packages>

Diff for: src/Orchard.Web/Modules/Orchard.ContentPreview/Orchard.ContentPreview.csproj

+4-4
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@
6262
<Reference Include="Microsoft.Owin, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
6363
<HintPath>..\..\..\packages\Microsoft.Owin.4.2.2\lib\net45\Microsoft.Owin.dll</HintPath>
6464
</Reference>
65-
<Reference Include="Microsoft.Owin.Host.SystemWeb, Version=4.1.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
66-
<HintPath>..\..\..\packages\Microsoft.Owin.Host.SystemWeb.4.1.1\lib\net45\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
65+
<Reference Include="Microsoft.Owin.Host.SystemWeb, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
66+
<HintPath>..\..\..\packages\Microsoft.Owin.Host.SystemWeb.4.2.2\lib\net45\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
6767
</Reference>
68-
<Reference Include="Microsoft.Owin.Security, Version=4.1.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
69-
<HintPath>..\..\..\packages\Microsoft.Owin.Security.4.1.1\lib\net45\Microsoft.Owin.Security.dll</HintPath>
68+
<Reference Include="Microsoft.Owin.Security, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
69+
<HintPath>..\..\..\packages\Microsoft.Owin.Security.4.2.2\lib\net45\Microsoft.Owin.Security.dll</HintPath>
7070
</Reference>
7171
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
7272
<HintPath>..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>

Diff for: src/Orchard.Web/Modules/Orchard.ContentPreview/packages.config

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
77
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net48" />
88
<package id="Microsoft.Owin" version="4.2.2" targetFramework="net48" />
9-
<package id="Microsoft.Owin.Host.SystemWeb" version="4.1.1" targetFramework="net48" />
10-
<package id="Microsoft.Owin.Security" version="4.1.1" targetFramework="net48" />
9+
<package id="Microsoft.Owin.Host.SystemWeb" version="4.2.2" targetFramework="net48" />
10+
<package id="Microsoft.Owin.Security" version="4.2.2" targetFramework="net48" />
1111
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
1212
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net48" />
1313
<package id="Owin" version="1.0" targetFramework="net48" />

Diff for: src/Orchard.Web/Modules/Orchard.Glimpse/Orchard.Glimpse.csproj

+4-4
Original file line numberDiff line numberDiff line change
@@ -86,11 +86,11 @@
8686
<Reference Include="Microsoft.Owin, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
8787
<HintPath>..\..\..\packages\Microsoft.Owin.4.2.2\lib\net45\Microsoft.Owin.dll</HintPath>
8888
</Reference>
89-
<Reference Include="Microsoft.Owin.Host.SystemWeb, Version=4.1.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
90-
<HintPath>..\..\..\packages\Microsoft.Owin.Host.SystemWeb.4.1.1\lib\net45\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
89+
<Reference Include="Microsoft.Owin.Host.SystemWeb, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
90+
<HintPath>..\..\..\packages\Microsoft.Owin.Host.SystemWeb.4.2.2\lib\net45\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
9191
</Reference>
92-
<Reference Include="Microsoft.Owin.Security, Version=4.1.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
93-
<HintPath>..\..\..\packages\Microsoft.Owin.Security.4.1.1\lib\net45\Microsoft.Owin.Security.dll</HintPath>
92+
<Reference Include="Microsoft.Owin.Security, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
93+
<HintPath>..\..\..\packages\Microsoft.Owin.Security.4.2.2\lib\net45\Microsoft.Owin.Security.dll</HintPath>
9494
</Reference>
9595
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
9696
<HintPath>..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>

Diff for: src/Orchard.Web/Modules/Orchard.Glimpse/packages.config

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
1515
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net48" />
1616
<package id="Microsoft.Owin" version="4.2.2" targetFramework="net48" />
17-
<package id="Microsoft.Owin.Host.SystemWeb" version="4.1.1" targetFramework="net48" />
18-
<package id="Microsoft.Owin.Security" version="4.1.1" targetFramework="net48" />
17+
<package id="Microsoft.Owin.Host.SystemWeb" version="4.2.2" targetFramework="net48" />
18+
<package id="Microsoft.Owin.Security" version="4.2.2" targetFramework="net48" />
1919
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
2020
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net48" />
2121
<package id="NHibernate" version="5.3.10" targetFramework="net48" />

Diff for: src/Orchard.Web/Modules/Orchard.MediaLibrary.WebSearch/Orchard.MediaLibrary.WebSearch.csproj

+4-4
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,11 @@
6262
<Reference Include="Microsoft.Owin, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
6363
<HintPath>..\..\..\packages\Microsoft.Owin.4.2.2\lib\net45\Microsoft.Owin.dll</HintPath>
6464
</Reference>
65-
<Reference Include="Microsoft.Owin.Host.SystemWeb, Version=4.1.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
66-
<HintPath>..\..\..\packages\Microsoft.Owin.Host.SystemWeb.4.1.1\lib\net45\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
65+
<Reference Include="Microsoft.Owin.Host.SystemWeb, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
66+
<HintPath>..\..\..\packages\Microsoft.Owin.Host.SystemWeb.4.2.2\lib\net45\Microsoft.Owin.Host.SystemWeb.dll</HintPath>
6767
</Reference>
68-
<Reference Include="Microsoft.Owin.Security, Version=4.1.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
69-
<HintPath>..\..\..\packages\Microsoft.Owin.Security.4.1.1\lib\net45\Microsoft.Owin.Security.dll</HintPath>
68+
<Reference Include="Microsoft.Owin.Security, Version=4.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
69+
<HintPath>..\..\..\packages\Microsoft.Owin.Security.4.2.2\lib\net45\Microsoft.Owin.Security.dll</HintPath>
7070
</Reference>
7171
<Reference Include="Microsoft.Web.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
7272
<HintPath>..\..\..\packages\Microsoft.Web.Infrastructure.1.0.0.0\lib\net40\Microsoft.Web.Infrastructure.dll</HintPath>

Diff for: src/Orchard.Web/Modules/Orchard.MediaLibrary.WebSearch/packages.config

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
<package id="Microsoft.AspNet.WebPages" version="3.2.7" targetFramework="net48" />
99
<package id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="2.0.1" targetFramework="net48" />
1010
<package id="Microsoft.Owin" version="4.2.2" targetFramework="net48" />
11-
<package id="Microsoft.Owin.Host.SystemWeb" version="4.1.1" targetFramework="net48" />
12-
<package id="Microsoft.Owin.Security" version="4.1.1" targetFramework="net48" />
11+
<package id="Microsoft.Owin.Host.SystemWeb" version="4.2.2" targetFramework="net48" />
12+
<package id="Microsoft.Owin.Security" version="4.2.2" targetFramework="net48" />
1313
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net48" />
1414
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net48" />
1515
<package id="Owin" version="1.0" targetFramework="net48" />

0 commit comments

Comments
 (0)