Skip to content

Commit 404615e

Browse files
committed
Merge branch '6.0' into 6.0-test-fixes
# Conflicts: # Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/Other.cs # Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/Reprocessing.cs
2 parents 01b288c + 3c311c5 commit 404615e

File tree

12 files changed

+419
-265
lines changed

12 files changed

+419
-265
lines changed

ChangeLog/6.0.6_dev.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[main] Fixed possible cases of broken serialization due to comparers
2+
[main] Fixed rare cases of insert wrong data into some table columns for SingleTable hierarchies
3+
[sqlserver] Fixed incorrect DateTimeOffset.Date part extraction
4+
[sqlserver] Improved translation of DateTimeOffset.LocalDateTime and DateTimeOffset.TimeOfDay parts extraction
5+
[postgresql] Improved performance of First(), FirstOrDefault() being subqueries
6+
[postgresql] Improved translation of Math.Ceiling(), Math.Truncate() and Math.Floor()
7+
[reprocessing] ExecuteActionStrategy.Execute doesn't get external session though Session.Current at all
8+
[reprocessing] Introduced DomainExtension.WithSession and IExecuteConfiguration WithSession methods to pass external session

Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/Other.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using NUnit.Framework;
44
using TestCommon.Model;
55
using Xtensive.Orm.Configuration;
6-
using Xtensive.Orm.Reprocessing.Configuration;
76

87
namespace Xtensive.Orm.Reprocessing.Tests
98
{
@@ -53,9 +52,9 @@ public void NestedNewSession()
5352
[Test]
5453
public void NestedSessionReuse()
5554
{
56-
Domain.Execute(
57-
session1 => Domain.Execute(
58-
session2 => Assert.That(session1, Is.SameAs(session2))));
55+
Domain.Execute(session1 =>
56+
Domain.WithSession(session1)
57+
.Execute(session2 => Assert.That(session1, Is.SameAs(session2))));
5958
}
6059

6160
[Test]
@@ -75,13 +74,15 @@ public void Test()
7574
[Test]
7675
public void ParentIsDisconnectedState()
7776
{
78-
Domain.Execute(session => { _ = new Bar(session); });
77+
Domain.Execute(session => {
78+
_ = new Bar(session);
79+
});
7980
using (var session = Domain.OpenSession(new SessionConfiguration(SessionOptions.ClientProfile)))
8081
using(session.Activate()) {
8182
var bar = session.Query.All<Bar>().FirstOrDefault();
82-
bar=new Bar(session);
83+
bar = new Bar(session);
8384
session.SaveChanges();
84-
Domain.Execute(session1 => {
85+
Domain.WithSession(session).Execute(session1 => {
8586
bar = session1.Query.All<Bar>().FirstOrDefault();
8687
bar = new Bar(session1);
8788
});
@@ -90,4 +91,4 @@ public void ParentIsDisconnectedState()
9091
Domain.Execute(session => Assert.That(session.Query.All<Bar>().Count(), Is.EqualTo(3)));
9192
}
9293
}
93-
}
94+
}

Extensions/Xtensive.Orm.Reprocessing.Tests/Tests/Reprocessing.cs

Lines changed: 84 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public void Deadlock(bool first, IsolationLevel? isolationLevel, TransactionOpen
3333
domain.WithStrategy(ExecuteActionStrategy.HandleUniqueConstraintViolation).WithIsolationLevel(isolationLevel.GetValueOrDefault(IsolationLevel.RepeatableRead)).WithTransactionOpenMode(transactionOpenMode.GetValueOrDefault(TransactionOpenMode.New)).Execute(
3434
session => {
3535
_ = Interlocked.Increment(ref Count);
36-
_ = new Bar2(session, DateTime.Now, Guid.NewGuid()) {Name = Guid.NewGuid().ToString()};
36+
_ = new Bar2(session, DateTime.Now, Guid.NewGuid()) { Name = Guid.NewGuid().ToString() };
3737
if (first) {
3838
_ = session.Query.All<Foo>().Lock(LockMode.Exclusive, LockBehavior.Wait).ToArray();
3939
if (wait1 != null) {
@@ -59,14 +59,13 @@ public void External(
5959
bool first,
6060
IsolationLevel? isolationLevel,
6161
TransactionOpenMode? transactionOpenMode,
62-
Action<bool, IsolationLevel?, TransactionOpenMode?> action)
62+
Action<Session, bool, IsolationLevel?, TransactionOpenMode?> action)
6363
{
6464
using (var session = domain.OpenSession())
65-
using (var tran = isolationLevel == null ? null : session.OpenTransaction())
66-
using (session.Activate()) {
65+
using (var tran = isolationLevel == null ? null : session.OpenTransaction()) {
6766
if (tran != null) {
6867
session.EnsureTransactionIsStarted();
69-
_ = new Bar2(session, DateTime.Now, Guid.NewGuid()) {Name = Guid.NewGuid().ToString()};
68+
_ = new Bar2(session, DateTime.Now, Guid.NewGuid()) { Name = Guid.NewGuid().ToString() };
7069
}
7170
if (first) {
7271
if (wait1 != null && wait2 != null) {
@@ -78,8 +77,8 @@ public void External(
7877
_ = wait2.Set();
7978
_ = wait1.WaitOne();
8079
}
81-
action(first, isolationLevel, transactionOpenMode);
82-
if (tran!=null) {
80+
action(session, first, isolationLevel, transactionOpenMode);
81+
if (tran != null) {
8382
tran.Complete();
8483
}
8584
}
@@ -92,22 +91,55 @@ public void Parent(
9291
IExecuteActionStrategy strategy,
9392
Action<bool, IsolationLevel?, TransactionOpenMode?> action)
9493
{
95-
domain.WithStrategy(strategy).WithIsolationLevel(isolationLevel.GetValueOrDefault(IsolationLevel.RepeatableRead)).WithTransactionOpenMode(transactionOpenMode.GetValueOrDefault(TransactionOpenMode.New)).Execute(
96-
session => {
97-
session.EnsureTransactionIsStarted();
98-
_ = new Bar2(session, DateTime.Now, Guid.NewGuid()) {Name = Guid.NewGuid().ToString()};
99-
if (first) {
100-
if (wait1 != null && wait2 != null) {
101-
_ = wait1.Set();
102-
_ = wait2.WaitOne();
94+
domain.WithStrategy(strategy)
95+
.WithIsolationLevel(isolationLevel.GetValueOrDefault(IsolationLevel.RepeatableRead))
96+
.WithTransactionOpenMode(transactionOpenMode.GetValueOrDefault(TransactionOpenMode.New))
97+
.Execute(
98+
session => {
99+
session.EnsureTransactionIsStarted();
100+
_ = new Bar2(session, DateTime.Now, Guid.NewGuid()) { Name = Guid.NewGuid().ToString() };
101+
if (first) {
102+
if (wait1 != null && wait2 != null) {
103+
_ = wait1.Set();
104+
_ = wait2.WaitOne();
105+
}
103106
}
104-
}
105-
else if (wait1!=null && wait2!=null) {
106-
_ = wait2.Set();
107-
_ = wait1.WaitOne();
108-
}
109-
action(first, isolationLevel, transactionOpenMode);
110-
});
107+
else if (wait1 != null && wait2 != null) {
108+
_ = wait2.Set();
109+
_ = wait1.WaitOne();
110+
}
111+
action(first, isolationLevel, transactionOpenMode);
112+
});
113+
}
114+
115+
public void Parent(
116+
Session session,
117+
bool first,
118+
IsolationLevel? isolationLevel,
119+
TransactionOpenMode? transactionOpenMode,
120+
IExecuteActionStrategy strategy,
121+
Action<bool, IsolationLevel?, TransactionOpenMode?> action)
122+
{
123+
domain.WithStrategy(strategy)
124+
.WithSession(session)
125+
.WithIsolationLevel(isolationLevel.GetValueOrDefault(IsolationLevel.RepeatableRead))
126+
.WithTransactionOpenMode(transactionOpenMode.GetValueOrDefault(TransactionOpenMode.New))
127+
.Execute(
128+
session => {
129+
session.EnsureTransactionIsStarted();
130+
_ = new Bar2(session, DateTime.Now, Guid.NewGuid()) { Name = Guid.NewGuid().ToString() };
131+
if (first) {
132+
if (wait1 != null && wait2 != null) {
133+
_ = wait1.Set();
134+
_ = wait2.WaitOne();
135+
}
136+
}
137+
else if (wait1 != null && wait2 != null) {
138+
_ = wait2.Set();
139+
_ = wait1.WaitOne();
140+
}
141+
action(first, isolationLevel, transactionOpenMode);
142+
});
111143
}
112144

113145
public void Run(
@@ -135,7 +167,7 @@ public void UniqueConstraintViolation(
135167
session => {
136168
_ = Interlocked.Increment(ref Count);
137169
session.EnsureTransactionIsStarted();
138-
_ = new Bar2(session, DateTime.Now, Guid.NewGuid()) {Name = Guid.NewGuid().ToString()};
170+
_ = new Bar2(session, DateTime.Now, Guid.NewGuid()) { Name = Guid.NewGuid().ToString() };
139171
var name = "test";
140172
if (!session.Query.All<Foo>().Any(a => a.Name == name)) {
141173
if (first) {
@@ -150,7 +182,7 @@ public void UniqueConstraintViolation(
150182
_ = wait1.WaitOne();
151183
wait2 = null;
152184
}
153-
_ = new Foo(session) {Name = name};
185+
_ = new Foo(session) { Name = name };
154186
}
155187
session.SaveChanges();
156188
});
@@ -163,19 +195,19 @@ public void UniqueConstraintViolationPrimaryKey(
163195
session => {
164196
_ = Interlocked.Increment(ref Count);
165197
session.EnsureTransactionIsStarted();
166-
_ = new Bar2(session, DateTime.Now, Guid.NewGuid()) {Name = Guid.NewGuid().ToString()};
198+
_ = new Bar2(session, DateTime.Now, Guid.NewGuid()) { Name = Guid.NewGuid().ToString() };
167199
var id = 10;
168-
if (session.Query.SingleOrDefault<Foo>(id) == null) {
200+
if (session.Query.SingleOrDefault<Foo>(id)==null) {
169201
var w1 = wait1;
170202
var w2 = wait2;
171203
if (first) {
172-
if (w1 != null && w2 != null) {
204+
if (w1!=null && w2!=null) {
173205
_ = w1.Set();
174206
_ = w2.WaitOne();
175207
wait1 = null;
176208
}
177209
}
178-
else if (w1 != null && w2 != null) {
210+
else if (w1!=null && w2!=null) {
179211
_ = w2.Set();
180212
_ = w1.WaitOne();
181213
wait2 = null;
@@ -278,8 +310,9 @@ public void Test()
278310
b,
279311
null,
280312
open,
281-
(b1, level1, open1) =>
313+
(s, b1, level1, open1) =>
282314
context.Parent(
315+
s,
283316
b1,
284317
IsolationLevel.Snapshot,
285318
open1,
@@ -290,30 +323,24 @@ public void Test()
290323

291324
//ExternalWithTransaction nested snapshot UniqueConstraint
292325
context = new Context(Domain);
293-
var ex =
294-
Assert.Throws<AggregateException>(
295-
() =>
296-
context.Run(
297-
IsolationLevel.Snapshot,
298-
null,
299-
(b, level, open) =>
300-
context.External(
301-
b,
302-
level,
303-
open,
304-
(b1, level1, open1) =>
305-
context.Parent(
306-
b1,
307-
level1,
308-
open1,
309-
ExecuteActionStrategy.HandleUniqueConstraintViolation,
310-
context.UniqueConstraintViolation))));
311-
Assert.That(
312-
ex.InnerExceptions.Single(),
313-
Is.TypeOf<InvalidOperationException>().Or.TypeOf<StorageException>().With.Property("InnerException").TypeOf
314-
<InvalidOperationException>());
315-
Assert.That(context.Count, Is.EqualTo(2));
316-
Assert.That(Bar2Count(), Is.EqualTo(3));
326+
context.Run(
327+
IsolationLevel.Snapshot,
328+
null,
329+
(b, level, open) =>
330+
context.External(
331+
b,
332+
level,
333+
open,
334+
(s, b1, level1, open1) =>
335+
context.Parent(
336+
s,
337+
b1,
338+
level1,
339+
open1,
340+
ExecuteActionStrategy.HandleUniqueConstraintViolation,
341+
context.UniqueConstraintViolation)));
342+
Assert.That(context.Count, Is.EqualTo(3));
343+
Assert.That(Bar2Count(), Is.EqualTo(6));
317344

318345
//nested UniqueConstraint with auto transaction
319346
context = new Context(Domain);
@@ -350,8 +377,8 @@ public void UniqueConstraintViolationExceptionPrimary()
350377
public void UniqueConstraintViolationExceptionUnique()
351378
{
352379
var i = 0;
353-
var b = false;
354-
ExecuteActionStrategy.HandleUniqueConstraintViolation.Error += (sender, args) => b = true;
380+
var errorNotified = false;
381+
ExecuteActionStrategy.HandleUniqueConstraintViolation.Error += (sender, args) => errorNotified = true;
355382
Domain.WithStrategy(ExecuteActionStrategy.HandleUniqueConstraintViolation).Execute(
356383
session => {
357384
_ = new Foo(session) { Name = "test" };
@@ -361,11 +388,11 @@ public void UniqueConstraintViolationExceptionUnique()
361388
}
362389
});
363390
Assert.That(i, Is.EqualTo(5));
364-
Assert.That(b, Is.True);
391+
Assert.That(errorNotified, Is.True);
365392
}
366393
}
367394
}
368395

369396
// ReSharper restore ReturnValueOfPureMethodIsNotUsed
370397
// ReSharper restore ConvertToConstant.Local
371-
// ReSharper restore AccessToModifiedClosure
398+
// ReSharper restore AccessToModifiedClosure

Extensions/Xtensive.Orm.Reprocessing/DomainExtensions.cs

Lines changed: 62 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
using System;
1+
using System;
22
using System.Transactions;
33
using Xtensive.Orm.Reprocessing.Configuration;
44

@@ -131,6 +131,18 @@ public static IExecuteConfiguration WithTransactionOpenMode(this Domain domain,
131131
return new ExecuteConfiguration(domain).WithTransactionOpenMode(transactionOpenMode);
132132
}
133133

134+
/// <summary>
135+
/// Starts <see cref="IExecuteConfiguration"/> flow
136+
/// and provides <see cref="Session"/> to use.
137+
/// </summary>
138+
/// <param name="domain">The domain.</param>
139+
/// <param name="session">The external session to use.</param>
140+
/// <returns>Created <see cref="IExecuteConfiguration"/>.</returns>
141+
public static IExecuteConfiguration WithSession(this Domain domain, Session session)
142+
{
143+
return new ExecuteConfiguration(domain).WithSession(session);
144+
}
145+
134146
#region Non-public methods
135147

136148
internal static void ExecuteInternal(
@@ -140,13 +152,33 @@ internal static void ExecuteInternal(
140152
IExecuteActionStrategy strategy,
141153
Action<Session> action)
142154
{
143-
ExecuteInternal<object>(
155+
_ = ExecuteInternal<object>(
144156
domain,
145157
isolationLevel,
146158
transactionOpenMode,
147159
strategy,
148-
a => {
149-
action(a);
160+
sessionInstance => {
161+
action(sessionInstance);
162+
return null;
163+
});
164+
}
165+
166+
internal static void ExecuteInternal(
167+
this Domain domain,
168+
Session session,
169+
IsolationLevel isolationLevel,
170+
TransactionOpenMode? transactionOpenMode,
171+
IExecuteActionStrategy strategy,
172+
Action<Session> action)
173+
{
174+
_ = ExecuteInternal<object>(
175+
domain,
176+
session,
177+
isolationLevel,
178+
transactionOpenMode,
179+
strategy,
180+
sessionInstance => {
181+
action(sessionInstance);
150182
return null;
151183
});
152184
}
@@ -158,14 +190,37 @@ internal static T ExecuteInternal<T>(
158190
IExecuteActionStrategy strategy,
159191
Func<Session, T> func)
160192
{
161-
ReprocessingConfiguration config = domain.GetReprocessingConfiguration();
162-
if (strategy==null)
193+
var config = domain.GetReprocessingConfiguration();
194+
if (strategy == null) {
163195
strategy = ExecuteActionStrategy.GetSingleton(config.DefaultExecuteStrategy);
164-
if (transactionOpenMode==null)
196+
}
197+
if (transactionOpenMode == null) {
165198
transactionOpenMode = config.DefaultTransactionOpenMode;
199+
}
166200
return strategy.Execute(new ExecutionContext<T>(domain, isolationLevel, transactionOpenMode.Value, func));
167201
}
168202

203+
internal static T ExecuteInternal<T>(
204+
this Domain domain,
205+
Session session,
206+
IsolationLevel isolationLevel,
207+
TransactionOpenMode? transactionOpenMode,
208+
IExecuteActionStrategy strategy,
209+
Func<Session, T> func)
210+
{
211+
var config = domain.GetReprocessingConfiguration();
212+
if (strategy == null) {
213+
strategy = ExecuteActionStrategy.GetSingleton(config.DefaultExecuteStrategy);
214+
}
215+
if (transactionOpenMode == null) {
216+
transactionOpenMode = config.DefaultTransactionOpenMode;
217+
}
218+
if (session.IsDisposed) {
219+
throw new ObjectDisposedException(nameof(session));
220+
}
221+
return strategy.Execute(new ExecutionContext<T>(domain, session, isolationLevel, transactionOpenMode.Value, func));
222+
}
223+
169224
#endregion
170225
}
171226
}

0 commit comments

Comments
 (0)