Skip to content

Commit 27b7fe7

Browse files
authored
Merge pull request #162 from DataObjects-NET/master-silent-table-cleanup-issue-extra
Better way to handle silent table cleanup on table movement to another hierarchy
2 parents 2da96f7 + 0299025 commit 27b7fe7

20 files changed

+7929
-1762
lines changed

Orm/Xtensive.Orm.Tests/Upgrade/ConflictsByTable/ColumnTypeChangeInNewHierarchy.cs

+550
Large diffs are not rendered by default.

Orm/Xtensive.Orm.Tests/Upgrade/ConflictsByTable/ComplexTest.cs

+1,355
Large diffs are not rendered by default.

Orm/Xtensive.Orm.Tests/Upgrade/ConflictsByTable/ComplextTestModel.cs

+1,968
Large diffs are not rendered by default.

Orm/Xtensive.Orm.Tests/Upgrade/ConflictsByTable/ExactTableStructureNoGeneratorTest.cs

+451
Large diffs are not rendered by default.

Orm/Xtensive.Orm.Tests/Upgrade/ConflictsByTable/ExactTableStructureWithGeneratorTest.cs

+470
Large diffs are not rendered by default.

Orm/Xtensive.Orm.Tests/Upgrade/ConflictsByTable/NewColumnInNewHierarchyTest.cs

+480
Large diffs are not rendered by default.

Orm/Xtensive.Orm.Tests/Upgrade/ConflictsByTable/PrimaryKeyNameChangedNoGeneratorTest.cs

+448
Large diffs are not rendered by default.

Orm/Xtensive.Orm.Tests/Upgrade/ConflictsByTable/PrimaryKeyNameChangedWithGeneratorTest.cs

+466
Large diffs are not rendered by default.

Orm/Xtensive.Orm.Tests/Upgrade/ConflictsByTable/RemovedColumnInNewHierarchyTest.cs

+519
Large diffs are not rendered by default.

Orm/Xtensive.Orm.Tests/Upgrade/ConflictsByTable/RenamedColumnInNewHierarchyTest.cs

+536
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,283 @@
1+
// Copyright (C) 2021 Xtensive LLC.
2+
// This code is distributed under MIT license terms.
3+
// See the License.txt file in the project root for more information.
4+
5+
using System;
6+
using System.Collections.Generic;
7+
using System.Linq;
8+
using System.Text;
9+
using System.Threading.Tasks;
10+
using NUnit.Framework;
11+
using Xtensive.Core;
12+
using Xtensive.Modelling.Actions;
13+
using Xtensive.Orm.Configuration;
14+
using Xtensive.Orm.Model;
15+
using Xtensive.Orm.Upgrade;
16+
using V1 = Xtensive.Orm.Tests.Upgrade.ConflictsByTable.ExactTableStructureNoGeneratorTestModel.Before;
17+
using V2 = Xtensive.Orm.Tests.Upgrade.ConflictsByTable.ExactTableStructureNoGeneratorTestModel.After;
18+
using TheTestHelper = Xtensive.Orm.Tests.Upgrade.ConflictsByTable.ExactTableStructureNoGeneratorTestModel.TestHelper;
19+
20+
namespace Xtensive.Orm.Tests.Upgrade.ConflictsByTable
21+
{
22+
public abstract class TestBase
23+
{
24+
[Test]
25+
[TestCase(InheritanceSchema.SingleTable, true)]
26+
[TestCase(InheritanceSchema.ClassTable, true)]
27+
[TestCase(InheritanceSchema.ConcreteTable, true)]
28+
[TestCase(InheritanceSchema.SingleTable, false)]
29+
[TestCase(InheritanceSchema.ClassTable, false)]
30+
[TestCase(InheritanceSchema.ConcreteTable, false)]
31+
public async ValueTask PerformSafelyTest(InheritanceSchema inheritanceSchema, bool asyncBuild)
32+
{
33+
var initDomainTypes = GetTypes(inheritanceSchema, false);
34+
BuildAndPopulateDomain(initDomainTypes, DomainUpgradeMode.Recreate);
35+
36+
var upgradeDomainTypes = GetTypes(inheritanceSchema, true);
37+
var ex = (asyncBuild)
38+
? Assert.ThrowsAsync<SchemaSynchronizationException>(async () => { using (await BuildDomainAsync(DomainUpgradeMode.PerformSafely, upgradeDomainTypes)) ; })
39+
: Assert.Throws<SchemaSynchronizationException>(() => { using (BuildDomain(DomainUpgradeMode.PerformSafely, upgradeDomainTypes)) ; });
40+
41+
CheckComparisonResult(inheritanceSchema, ex.ComparisonResult);
42+
43+
initDomainTypes = GetTypes(inheritanceSchema, false);
44+
if (asyncBuild) {
45+
await using (var domain = await BuildDomainAsync(DomainUpgradeMode.Validate, initDomainTypes))
46+
await using (var session = await domain.OpenSessionAsync())
47+
await using (var tx = await session.OpenTransactionAsync()) {
48+
ValidateDataRemains(inheritanceSchema, session);
49+
}
50+
}
51+
else {
52+
using (var domain = BuildDomain(DomainUpgradeMode.Validate, initDomainTypes))
53+
using (var session = domain.OpenSession())
54+
using (var tx = session.OpenTransaction()) {
55+
ValidateDataRemains(inheritanceSchema, session);
56+
}
57+
}
58+
}
59+
60+
[Test]
61+
[TestCase(InheritanceSchema.SingleTable, true)]
62+
[TestCase(InheritanceSchema.ClassTable, true)]
63+
[TestCase(InheritanceSchema.ConcreteTable, true)]
64+
[TestCase(InheritanceSchema.SingleTable, false)]
65+
[TestCase(InheritanceSchema.ClassTable, false)]
66+
[TestCase(InheritanceSchema.ConcreteTable, false)]
67+
public void PerformSafelyWithHintsTest(InheritanceSchema inheritanceSchema, bool asyncBuild)
68+
{
69+
var initDomainTypes = GetTypes(inheritanceSchema, false);
70+
BuildAndPopulateDomain(initDomainTypes, DomainUpgradeMode.Recreate);
71+
72+
var upgradeDomainTypes = GetTypes(inheritanceSchema, true, true);
73+
Domain domain = null;
74+
try {
75+
if (asyncBuild) {
76+
Assert.DoesNotThrowAsync(async () => domain = await BuildDomainAsync(DomainUpgradeMode.PerformSafely, upgradeDomainTypes));
77+
}
78+
else {
79+
Assert.DoesNotThrow(() => domain = BuildDomain(DomainUpgradeMode.PerformSafely, upgradeDomainTypes));
80+
}
81+
}
82+
catch (SuccessException) {
83+
domain.DisposeSafely();
84+
throw;
85+
}
86+
using (var session = domain.OpenSession())
87+
using (var tx = session.OpenTransaction()) {
88+
ValidateDataExists(inheritanceSchema, session);
89+
}
90+
}
91+
92+
[Test]
93+
[TestCase(InheritanceSchema.SingleTable, true)]
94+
[TestCase(InheritanceSchema.ClassTable, true)]
95+
[TestCase(InheritanceSchema.ConcreteTable, true)]
96+
[TestCase(InheritanceSchema.SingleTable, false)]
97+
[TestCase(InheritanceSchema.ClassTable, false)]
98+
[TestCase(InheritanceSchema.ConcreteTable, false)]
99+
public void PerformTest(InheritanceSchema inheritanceSchema, bool asyncBuild)
100+
{
101+
var initDomainTypes = GetTypes(inheritanceSchema, false);
102+
BuildAndPopulateDomain(initDomainTypes, DomainUpgradeMode.Recreate);
103+
104+
var upgradeDomainTypes = GetTypes(inheritanceSchema, true);
105+
106+
Domain domain = null;
107+
try {
108+
if (asyncBuild) {
109+
Assert.DoesNotThrowAsync(async () => domain = await BuildDomainAsync(DomainUpgradeMode.Perform, upgradeDomainTypes));
110+
}
111+
else {
112+
Assert.DoesNotThrow(() => domain = BuildDomain(DomainUpgradeMode.Perform, upgradeDomainTypes));
113+
}
114+
}
115+
catch (SuccessException) {
116+
domain.DisposeSafely();
117+
throw;
118+
}
119+
using (var session = domain.OpenSession())
120+
using (var tx = session.OpenTransaction()) {
121+
ValidateDataDisapeared(inheritanceSchema, session);
122+
}
123+
}
124+
125+
[Test]
126+
[TestCase(InheritanceSchema.SingleTable, true)]
127+
[TestCase(InheritanceSchema.ClassTable, true)]
128+
[TestCase(InheritanceSchema.ConcreteTable, true)]
129+
[TestCase(InheritanceSchema.SingleTable, false)]
130+
[TestCase(InheritanceSchema.ClassTable, false)]
131+
[TestCase(InheritanceSchema.ConcreteTable, false)]
132+
public void PerformWithHintsTest(InheritanceSchema inheritanceSchema, bool asyncBuild)
133+
{
134+
var initDomainTypes = GetTypes(inheritanceSchema, false);
135+
BuildAndPopulateDomain(initDomainTypes, DomainUpgradeMode.Recreate);
136+
137+
var upgradeDomainTypes = GetTypes(inheritanceSchema, true, true);
138+
139+
Domain domain = null;
140+
try {
141+
if (asyncBuild) {
142+
Assert.DoesNotThrowAsync(async () => domain = await BuildDomainAsync(DomainUpgradeMode.Perform, upgradeDomainTypes));
143+
}
144+
else {
145+
Assert.DoesNotThrow(() => domain = BuildDomain(DomainUpgradeMode.Perform, upgradeDomainTypes));
146+
}
147+
}
148+
catch (SuccessException) {
149+
domain.DisposeSafely();
150+
throw;
151+
}
152+
using (var session = domain.OpenSession())
153+
using (var tx = session.OpenTransaction()) {
154+
ValidateDataExists(inheritanceSchema, session);
155+
}
156+
}
157+
158+
159+
protected abstract void CheckSingleTableComparisonResult(SchemaComparisonResult comparisonResult);
160+
protected abstract void CheckConcreteTableComparisonResult(SchemaComparisonResult comparisonResult);
161+
protected abstract void CheckClassTableComparisonResult(SchemaComparisonResult comparisonResult);
162+
163+
protected abstract void ValidateSingleTableDataRemains(Session session);
164+
protected abstract void ValidateSingleTableDataExists(Session session);
165+
protected abstract void ValidateSingleTableDataDisapeared(Session session);
166+
167+
protected abstract void ValidateConcreteTableDataRemains(Session session);
168+
protected abstract void ValidateConcreteTableDataExists(Session session);
169+
protected abstract void ValidateConcreteTableDataDisapeared(Session session);
170+
171+
protected abstract void ValidateClassTableDataRemains(Session session);
172+
protected abstract void ValidateClassTableDataExists(Session session);
173+
protected abstract void ValidateClassTableDataDisapeared(Session session);
174+
175+
protected abstract void PopulateSingleTableDomain(Session session);
176+
protected abstract void PopulateConcreteTableDomain(Session session);
177+
protected abstract void PopulateClassTableDomain(Session session);
178+
179+
protected abstract Type[] GetTypes(InheritanceSchema inheritanceSchema, bool isAfter, bool? withHints = null);
180+
181+
private void CheckComparisonResult(InheritanceSchema inheritanceSchema, SchemaComparisonResult comparisonResult)
182+
{
183+
switch (inheritanceSchema) {
184+
case InheritanceSchema.ClassTable:
185+
CheckClassTableComparisonResult(comparisonResult);
186+
break;
187+
case InheritanceSchema.ConcreteTable:
188+
CheckConcreteTableComparisonResult(comparisonResult);
189+
break;
190+
case InheritanceSchema.SingleTable:
191+
CheckSingleTableComparisonResult(comparisonResult);
192+
break;
193+
}
194+
}
195+
196+
private void ValidateDataExists(InheritanceSchema inheritanceSchema, Session session)
197+
{
198+
switch (inheritanceSchema) {
199+
case InheritanceSchema.ClassTable:
200+
ValidateClassTableDataExists(session);
201+
break;
202+
case InheritanceSchema.ConcreteTable:
203+
ValidateConcreteTableDataExists(session);
204+
break;
205+
case InheritanceSchema.SingleTable:
206+
ValidateSingleTableDataExists(session);
207+
break;
208+
}
209+
}
210+
211+
private void ValidateDataRemains(InheritanceSchema inheritanceSchema, Session session)
212+
{
213+
switch (inheritanceSchema) {
214+
case InheritanceSchema.ClassTable:
215+
ValidateClassTableDataRemains(session);
216+
break;
217+
case InheritanceSchema.ConcreteTable:
218+
ValidateConcreteTableDataRemains(session);
219+
break;
220+
case InheritanceSchema.SingleTable:
221+
ValidateSingleTableDataRemains(session);
222+
break;
223+
}
224+
}
225+
226+
private void ValidateDataDisapeared(InheritanceSchema inheritanceSchema, Session session)
227+
{
228+
switch (inheritanceSchema) {
229+
case InheritanceSchema.ClassTable:
230+
ValidateClassTableDataDisapeared(session);
231+
break;
232+
case InheritanceSchema.ConcreteTable:
233+
ValidateConcreteTableDataDisapeared(session);
234+
break;
235+
case InheritanceSchema.SingleTable:
236+
ValidateSingleTableDataDisapeared(session);
237+
break;
238+
}
239+
}
240+
241+
private void BuildAndPopulateDomain(Type[] types, DomainUpgradeMode upgradeMode)
242+
{
243+
using (var initialDomain = BuildDomain(upgradeMode, types))
244+
using (var session = initialDomain.OpenSession())
245+
using (var t = session.OpenTransaction()) {
246+
var schema = initialDomain.Model.Hierarchies.First(h => !h.Root.IsSystem).InheritanceSchema;
247+
switch (schema) {
248+
case InheritanceSchema.SingleTable:
249+
PopulateSingleTableDomain(session);
250+
break;
251+
case InheritanceSchema.ClassTable:
252+
PopulateClassTableDomain(session);
253+
break;
254+
case InheritanceSchema.ConcreteTable:
255+
PopulateConcreteTableDomain(session);
256+
break;
257+
}
258+
259+
t.Complete();
260+
}
261+
}
262+
263+
private Domain BuildDomain(DomainUpgradeMode mode, Type[] types)
264+
{
265+
var configuration = BuildConfiguration(mode, types);
266+
return Domain.Build(configuration);
267+
}
268+
269+
private Task<Domain> BuildDomainAsync(DomainUpgradeMode mode, Type[] types)
270+
{
271+
var configuration = BuildConfiguration(mode, types);
272+
return Domain.BuildAsync(configuration);
273+
}
274+
275+
private DomainConfiguration BuildConfiguration(DomainUpgradeMode mode, Type[] types)
276+
{
277+
var configuration = DomainConfigurationFactory.Create();
278+
types.ForEach(t => configuration.Types.Register(t));
279+
configuration.UpgradeMode = mode;
280+
return configuration;
281+
}
282+
}
283+
}

0 commit comments

Comments
 (0)