Skip to content

Commit 7d805c5

Browse files
committed
Merge branch '6.0' into 6.0-prefetch-entityset-issue
2 parents 000ffad + 16678ef commit 7d805c5

File tree

7 files changed

+521
-153
lines changed

7 files changed

+521
-153
lines changed

Extensions/Xtensive.Orm.Logging.log4net/Xtensive.Orm.Logging.log4net.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
<AssemblyOriginatorKeyFile>..\Extensions.snk</AssemblyOriginatorKeyFile>
1515
</PropertyGroup>
1616
<ItemGroup>
17-
<PackageReference Include="log4net" Version="2.0.8" />
17+
<PackageReference Include="log4net" Version="2.0.10" />
1818
</ItemGroup>
1919
<ItemGroup>
2020
<ProjectReference Include="..\..\Orm\Xtensive.Orm\Xtensive.Orm.csproj" />
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
// Copyright (C) 2020-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;
10+
using System.Threading.Tasks;
11+
using System.Transactions;
12+
using NUnit.Framework;
13+
using Xtensive.Core;
14+
using Xtensive.Orm.Configuration;
15+
using Xtensive.Orm.Model;
16+
using Xtensive.Orm.Services;
17+
using Xtensive.Orm.Tests.Issues.IssueGitHub0110_SimpleCommandProcessorOverridesOriginalExceptionModel;
18+
19+
namespace Xtensive.Orm.Tests.Issues.IssueGitHub0110_SimpleCommandProcessorOverridesOriginalExceptionModel
20+
{
21+
[HierarchyRoot(InheritanceSchema.ConcreteTable)]
22+
public class Bin : Entity
23+
{
24+
[Field, Key]
25+
public long Id { get; private set; }
26+
27+
public Bin(Session session)
28+
: base(session)
29+
{
30+
}
31+
}
32+
33+
[HierarchyRoot(InheritanceSchema.ConcreteTable)]
34+
[Index("Name", Unique = true)]
35+
[Index(nameof(Active), nameof(N), nameof(M))]
36+
public class InventoryBalance : Entity
37+
{
38+
[Field, Key]
39+
public long Id { get; private set; }
40+
41+
[Field(Nullable = false)]
42+
public Bin Bin { get; private set; }
43+
44+
[Field]
45+
public bool Active { get; set; }
46+
47+
[Field]
48+
public string Name { get; set; }
49+
50+
[Field]
51+
public decimal N { get; set; }
52+
53+
[Field]
54+
public decimal M { get; set; }
55+
56+
[Field(DefaultSqlExpression = "GETUTCDATE()")]
57+
public DateTime ModifiedOn { get; set; }
58+
59+
public InventoryBalance(Session session, string name, Bin bin)
60+
: base(session)
61+
{
62+
Name = name;
63+
Active = true;
64+
Bin = bin;
65+
}
66+
}
67+
68+
public class OperationState
69+
{
70+
public Exception CatchendException { get; set; }
71+
72+
public bool Ended { get; set; }
73+
74+
public Domain Domain { get; }
75+
76+
public OperationState(Domain domain)
77+
{
78+
Domain = domain;
79+
}
80+
}
81+
}
82+
83+
namespace Xtensive.Orm.Tests.Issues
84+
{
85+
public class IssueGitHub0110_SimpleCommandProcessorOverridesOriginalException : AutoBuildTest
86+
{
87+
private static ManualResetEvent theStarter;
88+
89+
protected override void CheckRequirements() => Require.ProviderIs(StorageProvider.SqlServer);
90+
91+
protected override DomainConfiguration BuildConfiguration()
92+
{
93+
var configuration = base.BuildConfiguration();
94+
configuration.Types.Register(typeof(InventoryBalance).Assembly, typeof(InventoryBalance).Namespace);
95+
configuration.UpgradeMode = DomainUpgradeMode.Recreate;
96+
97+
var defaultSessionConfig = configuration.Sessions.Default;
98+
if (defaultSessionConfig == null) {
99+
defaultSessionConfig = new SessionConfiguration(WellKnown.Sessions.Default, SessionOptions.ServerProfile);
100+
configuration.Sessions.Add(defaultSessionConfig);
101+
}
102+
103+
defaultSessionConfig.DefaultIsolationLevel = IsolationLevel.Snapshot;
104+
defaultSessionConfig.DefaultCommandTimeout = 60 * 60; // 60 min.
105+
106+
defaultSessionConfig.BatchSize = 1; //force to use SimpleCommandProcessor
107+
108+
return configuration;
109+
}
110+
111+
protected override void PopulateData()
112+
{
113+
using (var session = Domain.OpenSession())
114+
using (var tx = session.OpenTransaction()) {
115+
_ = new InventoryBalance(session, "aaa", new Bin(session));
116+
tx.Complete();
117+
}
118+
}
119+
120+
[SetUp]
121+
public void InitStarter() => theStarter = new ManualResetEvent(false);
122+
123+
[TearDown]
124+
public void DisposeStarter()
125+
{
126+
theStarter.DisposeSafely();
127+
theStarter = null;
128+
}
129+
130+
[Test]
131+
public void MainTest()
132+
{
133+
var task1State = new OperationState(Domain);
134+
var task2State = new OperationState(Domain);
135+
136+
var task1 = new Task(Outer, task1State);
137+
var task2 = new Task(Outer, task2State);
138+
task1.Start();
139+
task2.Start();
140+
141+
Thread.Sleep(700);
142+
143+
_ = theStarter.Set();
144+
145+
while (!task1State.Ended && !task1State.Ended) {
146+
Thread.Sleep(100);
147+
}
148+
149+
var exception = task1State.CatchendException ?? task2State.CatchendException;
150+
Assert.That(exception, Is.Not.Null);
151+
Assert.That(exception, Is.InstanceOf<TransactionSerializationFailureException>());
152+
}
153+
154+
private static void Outer(object state)
155+
{
156+
var operationState = (OperationState) state;
157+
158+
try {
159+
using (var session = operationState.Domain.OpenSession(SessionType.User))
160+
using (var tx = session.OpenTransaction()) {
161+
var binId = session.Query.All<Bin>().First().Id;
162+
var bin = session.Query.SingleOrDefault<Bin>(binId);
163+
Inner(session, bin);
164+
tx.Complete();
165+
}
166+
operationState.Ended = true;
167+
}
168+
catch (Exception ex) {
169+
operationState.CatchendException = ex;
170+
operationState.Ended = true;
171+
}
172+
}
173+
174+
private static void Inner(Session session, Bin bin)
175+
{
176+
using (var tx = session.OpenTransaction()) {
177+
var doc = session.Query.All<InventoryBalance>().SingleOrDefault(o => o.Active == true && o.Bin == bin);
178+
doc.N += 1;
179+
_ = theStarter.WaitOne();
180+
tx.Complete();
181+
}
182+
}
183+
}
184+
}

Orm/Xtensive.Orm.Tests/Issues/IssueJira0546_IncorrectCachingOfQueries.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2014 Xtensive LLC.
1+
// Copyright (C) 2014-2021 Xtensive LLC.
22
// All rights reserved.
33
// For conditions of distribution and use, see license.
44
// Created by: Alexey Kulakov
@@ -54,16 +54,16 @@ public class Zone : Entity
5454

5555
namespace Xtensive.Orm.Tests.Issues
5656
{
57-
internal class BaseTask
57+
internal class IssueJira0546BaseTask
5858
{
5959
public int StartValue { get; set; }
6060

61-
public BaseTask(int startValue)
61+
public IssueJira0546BaseTask(int startValue)
6262
{
6363
StartValue = startValue;
6464
}
6565
}
66-
internal class Task: BaseTask
66+
internal class IssueJira0546Task : IssueJira0546BaseTask
6767
{
6868
public Session Session { get; private set; }
6969

@@ -117,7 +117,7 @@ orderby loc.Id
117117
return result;
118118
}
119119

120-
public Task(Session session, int startValue)
120+
public IssueJira0546Task(Session session, int startValue)
121121
: base(startValue)
122122
{
123123
this.Session = session;
@@ -284,7 +284,7 @@ private void TaskSequencesGenerator(Session session)
284284
var currentId = 1;
285285
var iterationsCount = 0;
286286
while (currentId<80) {
287-
var task = new Task(session, currentId);
287+
var task = new IssueJira0546Task(session, currentId);
288288
var previousId = currentId;
289289
currentId = task.GetMinimalLocationIdDelayedApi();
290290
Assert.AreEqual(previousId+1, currentId);
@@ -299,7 +299,7 @@ private void TaskSequencesGenerator(Session session)
299299
currentId = 1;
300300
iterationsCount = 0;
301301
while (currentId < 80) {
302-
var task = new Task(session, currentId);
302+
var task = new IssueJira0546Task(session, currentId);
303303
var previousId = currentId;
304304
currentId = task.GetMinimalLocationIdFutureApi();
305305
Assert.AreEqual(previousId + 1, currentId);
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
// Copyright (C) 2020 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+
// Created by: Alexey Kulakov
5+
// Created: 2020.11.16
6+
7+
using NUnit.Framework;
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Linq;
11+
using Xtensive.Orm.Configuration;
12+
using Xtensive.Orm.Tests.Issues.IssueJira0801_ReduntandColumnRemoverRemovesPartOfTempTableColumnsModel;
13+
14+
namespace Xtensive.Orm.Tests.Issues.IssueJira0801_ReduntandColumnRemoverRemovesPartOfTempTableColumnsModel
15+
{
16+
[HierarchyRoot]
17+
public class EquipmentStateRecord : Entity
18+
{
19+
[Field, Key]
20+
public long Id { get; private set; }
21+
22+
[Field]
23+
public DateTime StartDate { get; set; }
24+
25+
[Field]
26+
public DateTime? EndDate { get; set; }
27+
28+
[Field]
29+
public Equipment Equipment { get; set; }
30+
31+
[Field]
32+
public MachineStateType Type { get; set; }
33+
}
34+
35+
[HierarchyRoot]
36+
public class Equipment : Entity
37+
{
38+
[Field, Key]
39+
public long Id { get; private set; }
40+
}
41+
42+
public enum MachineStateType
43+
{
44+
Undefined = 0,
45+
Production = 1,
46+
EmergencyStop = 2,
47+
Adjustment = 3,
48+
SwitchedOn = 4,
49+
SwitchedOff = 5
50+
}
51+
52+
public class Segment
53+
{
54+
public long EquipmentId { get; set; }
55+
56+
public DateTime StartDate { get; set; }
57+
58+
public DateTime EndDate { get; set; }
59+
}
60+
}
61+
62+
namespace Xtensive.Orm.Tests.Issues
63+
{
64+
public class IssueJira0801_ReduntandColumnRemoverRemovesPartOfTempTableColumns : AutoBuildTest
65+
{
66+
private long equipmentId;
67+
68+
protected override void CheckRequirements() =>
69+
Require.AllFeaturesSupported(Providers.ProviderFeatures.TemporaryTables);
70+
71+
protected override DomainConfiguration BuildConfiguration()
72+
{
73+
var config = base.BuildConfiguration();
74+
config.Types.Register(typeof(EquipmentStateRecord).Assembly, typeof(EquipmentStateRecord).Namespace);
75+
return config;
76+
}
77+
78+
protected override void PopulateData()
79+
{
80+
using (var session = Domain.OpenSession())
81+
using (var tx = session.OpenTransaction()) {
82+
var equipment = new Equipment();
83+
equipmentId = equipment.Id;
84+
85+
foreach (var item in Enum.GetValues(typeof(MachineStateType)).Cast<MachineStateType>()) {
86+
_ = new EquipmentStateRecord() {
87+
Equipment = equipment,
88+
Type = item,
89+
StartDate = DateTime.Now.AddDays(-1),
90+
EndDate = DateTime.Now.AddHours(-1)
91+
};
92+
93+
_ = new EquipmentStateRecord() {
94+
Equipment = equipment,
95+
Type = item,
96+
StartDate = DateTime.Now.AddDays(-2),
97+
EndDate = DateTime.Now.AddHours(-2)
98+
};
99+
100+
_ = new EquipmentStateRecord() {
101+
Equipment = equipment,
102+
Type = item,
103+
StartDate = DateTime.Now.AddDays(-3),
104+
EndDate = DateTime.Now.AddHours(-3)
105+
};
106+
}
107+
108+
tx.Complete();
109+
}
110+
}
111+
112+
[Test]
113+
public void MainTest()
114+
{
115+
using (var session = Domain.OpenSession())
116+
using (var tx = session.OpenTransaction()) {
117+
var segments = GetSegments().Select(x => new { x.EquipmentId, x.StartDate, x.EndDate }).ToArray();
118+
var remoteSegments = session.Query.Store(segments);
119+
120+
var testQuery = session.Query.All<EquipmentStateRecord>()
121+
.Where(x => x.EndDate.HasValue)
122+
.Join(remoteSegments,
123+
record => record.Equipment.Id,
124+
segment => segment.EquipmentId,
125+
(record, segment) => new {
126+
EquipmentId = record.Equipment.Id,
127+
Type = record.Type,
128+
StateStartDate = record.StartDate,
129+
StateEndDate = record.EndDate.Value,
130+
SegmentStartDate = segment.StartDate,
131+
SegmentEndDate = segment.EndDate,
132+
StartTime = record.StartDate < segment.StartDate ? segment.StartDate : record.StartDate,
133+
EndTime = record.EndDate.Value > segment.EndDate ? segment.EndDate : record.EndDate.Value
134+
})
135+
.Where(x => x.StateStartDate < x.SegmentEndDate)
136+
.GroupBy(x => new { x.EquipmentId, x.Type }, x => x.EndTime - x.StartTime)
137+
.ToArray();
138+
}
139+
}
140+
141+
private IEnumerable<Segment> GetSegments()
142+
{
143+
yield return new Segment { EquipmentId = equipmentId, StartDate = DateTime.Now.AddDays(-1), EndDate = DateTime.Now };
144+
yield return new Segment { EquipmentId = equipmentId, StartDate = DateTime.Now.AddDays(-2), EndDate = DateTime.Now };
145+
yield return new Segment { EquipmentId = equipmentId, StartDate = DateTime.Now.AddDays(-3), EndDate = DateTime.Now };
146+
}
147+
}
148+
}

0 commit comments

Comments
 (0)