Skip to content

Commit 3e71a1c

Browse files
authored
Merge pull request #62 from DataObjects-NET/async-enumerable-1
DataObjects.Net async API
2 parents 516af15 + a7bcd87 commit 3e71a1c

562 files changed

Lines changed: 32087 additions & 16091 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

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

Lines changed: 104 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (C) 2012-2020 Xtensive LLC.
1+
// Copyright (C) 2012-2020 Xtensive LLC.
22
// This code is distributed under MIT license terms.
33
// See the License.txt file in the project root for more information.
44
// Created by: Alexander Ovchinnikov
@@ -7,9 +7,9 @@
77
using System;
88
using System.Collections.Generic;
99
using System.Linq;
10+
using System.Threading.Tasks;
1011
using NUnit.Framework;
1112
using TestCommon.Model;
12-
using Xtensive.Orm.Rse;
1313

1414
namespace Xtensive.Orm.BulkOperations.Tests
1515
{
@@ -37,6 +37,29 @@ public void CompositeKeyUpdate()
3737
}
3838
}
3939

40+
[Test]
41+
public async Task CompositeKeyUpdateAsync()
42+
{
43+
await using (Session session = await Domain.OpenSessionAsync()) {
44+
await using (TransactionScope trx = session.OpenTransaction()) {
45+
DateTime date1 = DateTime.Now;
46+
DateTime date2 = DateTime.Now.AddDays(1);
47+
Guid id1 = Guid.NewGuid();
48+
Guid id2 = Guid.NewGuid();
49+
var foo1 = new Bar2(session, date1, id1) {Name = "test"};
50+
var foo2 = new Bar2(session, date2, id1);
51+
var foo3 = new Bar2(session, date2, id2) {Name = "test"};
52+
int updated =
53+
await session.Query.All<Bar2>().Where(a => a.Name=="test").Set(a => a.Name, "abccba").UpdateAsync();
54+
Assert.That(updated, Is.EqualTo(2));
55+
Assert.That(foo1.Name, Is.EqualTo("abccba"));
56+
Assert.That(foo3.Name, Is.EqualTo("abccba"));
57+
Assert.That(foo2.Name, Is.Null);
58+
trx.Complete();
59+
}
60+
}
61+
}
62+
4063
[Test]
4164
public void SimpleDelete()
4265
{
@@ -64,6 +87,36 @@ public void SimpleDelete()
6487
}
6588
}
6689

90+
[Test]
91+
public async Task SimpleDeleteAsync()
92+
{
93+
await using (Session session = await Domain.OpenSessionAsync()) {
94+
await using (TransactionScope trx = session.OpenTransaction()) {
95+
var bar1 = new Bar(session) {Name = "test", Count = 3};
96+
var bar2 = new Bar(session);
97+
var bar3 = new Bar(session);
98+
bar3.Foo.Add(new Foo(session) {Name = "Foo"});
99+
string s = "test";
100+
101+
int deleted = await session.Query.All<Bar>().Where(a => a.Name==s).DeleteAsync();
102+
Assert.That(bar1.IsRemoved, Is.True);
103+
Assert.That(bar2.IsRemoved, Is.False);
104+
Assert.That(bar3.IsRemoved, Is.False);
105+
Assert.That(deleted, Is.EqualTo(1));
106+
107+
await session.Query.All<Bar>()
108+
.Where(a => a.Foo.Any(b => b.Name=="Foo"))
109+
.UpdateAsync(a => new Bar(null) {Name = ""});
110+
111+
deleted = await session.Query.All<Bar>().Where(a => a.Foo.Count(b => b.Name=="Foo")==0).DeleteAsync();
112+
Assert.That(bar2.IsRemoved, Is.True);
113+
Assert.That(bar3.IsRemoved, Is.False);
114+
Assert.That(deleted, Is.EqualTo(1));
115+
trx.Complete();
116+
}
117+
}
118+
}
119+
67120
[Test]
68121
public void SimpleInsert()
69122
{
@@ -93,6 +146,34 @@ public void SimpleInsert()
93146
}
94147
}
95148

149+
[Test]
150+
public async Task SimpleInsertAsync()
151+
{
152+
await using (Session session = await Domain.OpenSessionAsync()) {
153+
await using (TransactionScope trx = session.OpenTransaction()) {
154+
string s1 = "abccba";
155+
int i = 5;
156+
Key key = await session.Query.InsertAsync(
157+
() => new Bar(session) {Name = "test1" + s1, Count = i * 2 + 1, Description = null});
158+
Assert.That(key, Is.EqualTo(Key.Create<Bar>(session.Domain, 1)));
159+
var bar = session.Query.Single<Bar>(key);
160+
Assert.That(bar.Name, Is.EqualTo("test1abccba"));
161+
Assert.That(bar.Count, Is.EqualTo(11));
162+
Assert.That(bar.Description, Is.Null);
163+
164+
key = await session.Query.InsertAsync(
165+
() => new Bar(session) {Id = 100, Name = "test" + s1, Count = i * 2 + 1, Description = null});
166+
Assert.That(key, Is.EqualTo(Key.Create<Bar>(session.Domain, 100)));
167+
bar = session.Query.Single<Bar>(key);
168+
Assert.That(bar.Name, Is.EqualTo("testabccba"));
169+
Assert.That(bar.Count, Is.EqualTo(11));
170+
Assert.That(bar.Description, Is.Null);
171+
172+
trx.Complete();
173+
}
174+
}
175+
}
176+
96177
[Test]
97178
public void SimpleUpdate()
98179
{
@@ -114,6 +195,27 @@ public void SimpleUpdate()
114195
}
115196
}
116197

198+
[Test]
199+
public async Task SimpleUpdateAsync()
200+
{
201+
await using (Session session = await Domain.OpenSessionAsync()) {
202+
await using (TransactionScope trx = session.OpenTransaction()) {
203+
var bar1 = new Bar(session) {Name = "test", Count = 3};
204+
var bar2 = new Bar(session);
205+
string s = "test";
206+
string s1 = "abccba";
207+
int updated = await session.Query.All<Bar>()
208+
.Where(a => a.Name.Contains(s))
209+
.UpdateAsync(a => new Bar(session) {Name = a.Name + s1, Count = a.Count * 2, Description = null});
210+
Assert.That(bar1.Name, Is.EqualTo("testabccba"));
211+
Assert.That(bar1.Description, Is.Null);
212+
Assert.That(bar1.Count, Is.EqualTo(6));
213+
Assert.That(updated, Is.EqualTo(1));
214+
trx.Complete();
215+
}
216+
}
217+
}
218+
117219
[Test]
118220
public void SubqueryInsert()
119221
{
Lines changed: 82 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1-
using System;
2-
using System.Collections.Generic;
1+
// Copyright (C) 2019-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+
5+
using System;
36
using System.Diagnostics.Contracts;
47
using System.Linq;
58
using System.Linq.Expressions;
6-
using System.Reflection;
7-
using Xtensive.Orm;
9+
using System.Threading;
10+
using System.Threading.Tasks;
811

912
namespace Xtensive.Orm.BulkOperations
1013
{
@@ -19,10 +22,22 @@ public static class BulkExtensions
1922
/// <typeparam name="T">Type of the entity.</typeparam>
2023
/// <param name="query">The query.</param>
2124
/// <returns>Number of the deleted entities.</returns>
22-
public static int Delete<T>(this IQueryable<T> query) where T : class, IEntity
23-
{
24-
return new BulkDeleteOperation<T>(query).Execute();
25-
}
25+
public static int Delete<T>(this IQueryable<T> query) where T : class, IEntity =>
26+
new BulkDeleteOperation<T>(query).Execute();
27+
28+
/// <summary>
29+
/// Asynchronously executes bulk delete of entities specified by the query.
30+
/// </summary>
31+
/// <remarks>Multiple active operations in the same session instance are not supported. Use
32+
/// <see langword="await"/> to ensure that all asynchronous operations have completed before calling
33+
/// another method in this session.</remarks>
34+
/// <typeparam name="T">Type of the entity.</typeparam>
35+
/// <param name="query">The query.</param>
36+
/// <param name="token">The cancellation token to terminate execution if needed.</param>
37+
/// <returns>Number of the deleted entities.</returns>
38+
public static Task<int> DeleteAsync<T>(this IQueryable<T> query, CancellationToken token = default)
39+
where T : class, IEntity =>
40+
new BulkDeleteOperation<T>(query).ExecuteAsync(token);
2641

2742
/// <summary>
2843
/// Executes bulk update of entities specified by the query.
@@ -35,10 +50,8 @@ public static int Delete<T>(this IQueryable<T> query) where T : class, IEntity
3550
/// <returns>Instance of <see cref=" IUpdatable&lt;T&gt;"/>.</returns>
3651
[Pure]
3752
public static IUpdatable<T> Set<T, TResult>(this IQueryable<T> query, Expression<Func<T, TResult>> field,
38-
Expression<Func<T, TResult>> update) where T: IEntity
39-
{
40-
return new Updatable<T>(query, field, update);
41-
}
53+
Expression<Func<T, TResult>> update) where T: IEntity =>
54+
new Updatable<T>(query, field, update);
4255

4356
/// <summary>
4457
/// Executes bulk update of entities specified by the query.
@@ -51,10 +64,8 @@ public static IUpdatable<T> Set<T, TResult>(this IQueryable<T> query, Expression
5164
/// <returns>Instance of <see cref=" IUpdatable&lt;T&gt;"/>.</returns>
5265
[Pure]
5366
public static IUpdatable<T> Set<T, TResult>(this IUpdatable<T> query, Expression<Func<T, TResult>> field,
54-
Expression<Func<T, TResult>> update) where T: IEntity
55-
{
56-
return new Updatable<T>((Updatable<T>) query, field, update);
57-
}
67+
Expression<Func<T, TResult>> update) where T: IEntity =>
68+
new Updatable<T>((Updatable<T>) query, field, update);
5869

5970
/// <summary>
6071
/// Executes bulk update of entities specified by the query.
@@ -67,10 +78,8 @@ public static IUpdatable<T> Set<T, TResult>(this IUpdatable<T> query, Expression
6778
/// <returns>Instance of <see cref=" IUpdatable&lt;T&gt;"/>.</returns>
6879
[Pure]
6980
public static IUpdatable<T> Set<T, TResult>(this IQueryable<T> query, Expression<Func<T, TResult>> field,
70-
TResult value) where T: IEntity
71-
{
72-
return Set(query, field, a => value);
73-
}
81+
TResult value) where T: IEntity =>
82+
Set(query, field, a => value);
7483

7584
/// <summary>
7685
/// Executes bulk update of entities specified by the query.
@@ -83,10 +92,8 @@ public static IUpdatable<T> Set<T, TResult>(this IQueryable<T> query, Expression
8392
/// <returns>Instance of <see cref=" IUpdatable&lt;T&gt;"/>.</returns>
8493
[Pure]
8594
public static IUpdatable<T> Set<T, TResult>(this IUpdatable<T> query, Expression<Func<T, TResult>> field,
86-
TResult value) where T: IEntity
87-
{
88-
return Set(query, field, a => value);
89-
}
95+
TResult value) where T: IEntity =>
96+
Set(query, field, a => value);
9097

9198
/// <summary>
9299
/// Executes the UPDATE operation.
@@ -95,21 +102,46 @@ public static IUpdatable<T> Set<T, TResult>(this IUpdatable<T> query, Expression
95102
/// <param name="query">The query.</param>
96103
/// <param name="evaluator">The expression, that specify new values. Constructor parameters are ignored.</param>
97104
/// <returns>Number of updated entities.</returns>
98-
public static int Update<T>(this IQueryable<T> query, Expression<Func<T, T>> evaluator) where T : class, IEntity
99-
{
100-
return new BulkUpdateOperation<T>(query, evaluator).Execute();
101-
}
105+
public static int Update<T>(this IQueryable<T> query, Expression<Func<T, T>> evaluator) where T : class, IEntity =>
106+
new BulkUpdateOperation<T>(query, evaluator).Execute();
107+
108+
/// <summary>
109+
/// Asynchronously executes the UPDATE operation.
110+
/// </summary>
111+
/// <remarks>Multiple active operations in the same session instance are not supported. Use
112+
/// <see langword="await"/> to ensure that all asynchronous operations have completed before calling
113+
/// another method in this session.</remarks>
114+
/// <typeparam name="T">Type of the entity.</typeparam>
115+
/// <param name="query">The query.</param>
116+
/// <param name="evaluator">The expression, that specify new values. Constructor parameters are ignored.</param>
117+
/// <param name="token">The cancellation token to terminate execution if necessary.</param>
118+
/// <returns>Number of updated entities.</returns>
119+
public static Task<int> UpdateAsync<T>(this IQueryable<T> query, Expression<Func<T, T>> evaluator,
120+
CancellationToken token = default) where T : class, IEntity =>
121+
new BulkUpdateOperation<T>(query, evaluator).ExecuteAsync(token);
102122

103123
/// <summary>
104124
/// Executes the UPDATE operation.
105125
/// </summary>
106126
/// <typeparam name="T">Type of the entity.</typeparam>
107127
/// <param name="query">The query.</param>
108128
/// <returns>Number of updated entities.</returns>
109-
public static int Update<T>(this IUpdatable<T> query) where T : class, IEntity
110-
{
111-
return new BulkUpdateOperation<T>(query).Execute();
112-
}
129+
public static int Update<T>(this IUpdatable<T> query) where T : class, IEntity =>
130+
new BulkUpdateOperation<T>(query).Execute();
131+
132+
/// <summary>
133+
/// Asynchronously executes the UPDATE operation.
134+
/// </summary>
135+
/// <remarks>Multiple active operations in the same session instance are not supported. Use
136+
/// <see langword="await"/> to ensure that all asynchronous operations have completed before calling
137+
/// another method in this session.</remarks>
138+
/// <typeparam name="T">Type of the entity.</typeparam>
139+
/// <param name="query">The query.</param>
140+
/// <param name="token">The cancellation token to terminate execution if necessary.</param>
141+
/// <returns>Number of updated entities.</returns>
142+
public static Task<int> UpdateAsync<T>(this IUpdatable<T> query, CancellationToken token = default)
143+
where T : class, IEntity =>
144+
new BulkUpdateOperation<T>(query).ExecuteAsync(token);
113145

114146
/// <summary>
115147
/// Executes INSERT operation.
@@ -125,9 +157,23 @@ public static Key Insert<T>(this QueryEndpoint queryEndpoint, Expression<Func<T>
125157
return operation.Key;
126158
}
127159

128-
#region Non-public methods
129-
130-
131-
#endregion
160+
/// <summary>
161+
/// Asynchronously executes INSERT operation.
162+
/// </summary>
163+
/// <remarks>Multiple active operations in the same session instance are not supported. Use
164+
/// <see langword="await"/> to ensure that all asynchronous operations have completed before calling
165+
/// another method in this session.</remarks>
166+
/// <typeparam name="T">Type of the entity.</typeparam>
167+
/// <param name="queryEndpoint">The query endpoint.</param>
168+
/// <param name="evaluator">The expression, tha specify new values.</param>
169+
/// <param name="token">The cancellation token to terminate execution if necessary.</param>
170+
/// <returns>Key of the created entity.</returns>
171+
public static async Task<Key> InsertAsync<T>(this QueryEndpoint queryEndpoint, Expression<Func<T>> evaluator,
172+
CancellationToken token = default) where T : Entity
173+
{
174+
var operation = new InsertOperation<T>(queryEndpoint.Provider, evaluator);
175+
await operation.ExecuteAsync(token).ConfigureAwait(false);
176+
return operation.Key;
177+
}
132178
}
133179
}

0 commit comments

Comments
 (0)