Skip to content

Commit e29a100

Browse files
committed
Use StateLifetimeToken to control results cached in QueryResult
Also fix session's lifetime token immortality issue
1 parent 0d02757 commit e29a100

3 files changed

Lines changed: 21 additions & 3 deletions

File tree

Orm/Xtensive.Orm/Orm/Linq/Materialization/Materializer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public QueryResult<T> Invoke<T>(RecordSetReader recordSetReader, Session session
1616
{
1717
var reader = (IMaterializingReader<T>)
1818
materializeMethod.Invoke(recordSetReader, session, parameterContext);
19-
return new QueryResult<T>(reader);
19+
return new QueryResult<T>(reader, session.GetLifetimeToken());
2020
}
2121

2222
public Materializer(Func<RecordSetReader,Session,ParameterContext,object> materializeMethod)

Orm/Xtensive.Orm/Orm/QueryResult.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44

5+
using System;
56
using System.Collections;
67
using System.Collections.Generic;
78
using Xtensive.Orm.Linq.Materialization;
@@ -29,32 +30,47 @@ public EnumerableReader(IEnumerable<TItem> items)
2930
}
3031

3132
private readonly IMaterializingReader<TItem> reader;
33+
private readonly StateLifetimeToken lifetimeToken;
3234

3335
/// <inheritdoc/>
3436
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
3537

3638
/// <inheritdoc/>
37-
public IEnumerator<TItem> GetEnumerator() => reader.AsEnumerator();
39+
public IEnumerator<TItem> GetEnumerator()
40+
{
41+
EnsureResultsAlive();
42+
return reader.AsEnumerator();
43+
}
3844

3945
/// <summary>
4046
/// Transforms <see cref="QueryResult{TItem}"/> to an <see cref="IAsyncEnumerable{T}"/> sequence.
4147
/// </summary>
4248
public async IAsyncEnumerable<TItem> AsAsyncEnumerable()
4349
{
50+
EnsureResultsAlive();
4451
var enumerator = reader.AsAsyncEnumerator();
4552
while (await enumerator.MoveNextAsync().ConfigureAwait(false)) {
4653
yield return enumerator.Current;
4754
}
4855
}
4956

50-
internal QueryResult(IMaterializingReader<TItem> reader)
57+
private void EnsureResultsAlive()
58+
{
59+
if (lifetimeToken != null && !lifetimeToken.IsActive) {
60+
throw new InvalidOperationException(Strings.ExThisInstanceIsExpiredDueToTransactionBoundaries);
61+
}
62+
}
63+
64+
internal QueryResult(IMaterializingReader<TItem> reader, StateLifetimeToken lifetimeToken)
5165
{
5266
this.reader = reader;
67+
this.lifetimeToken = lifetimeToken;
5368
}
5469

5570
internal QueryResult(IEnumerable<TItem> items)
5671
{
5772
reader = new EnumerableReader(items);
73+
this.lifetimeToken = default;
5874
}
5975
}
6076
}

Orm/Xtensive.Orm/Orm/Session.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,8 @@ private async ValueTask DisposeImpl(bool isAsync)
585585
return;
586586
}
587587

588+
sessionLifetimeToken.Expire();
589+
588590
try {
589591
if (IsDebugEventLoggingEnabled) {
590592
OrmLog.Debug(Strings.LogSessionXDisposing, this);

0 commit comments

Comments
 (0)