Skip to content

Commit a81f91d

Browse files
committed
#29 using Dasync/AsyncEnumerator to faciliatate async iteration
1 parent 7ababa8 commit a81f91d

File tree

28 files changed

+442
-534
lines changed

28 files changed

+442
-534
lines changed

SubSonic.Tests/DAL/Asynchronous/AsynchronousTests.cs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ public override void SetupTestFixture()
2525

2626
string
2727
people_all = @"SELECT [T1].[ID], [T1].[FirstName], [T1].[MiddleInitial], [T1].[FamilyName], [T1].[FullName]
28+
FROM [dbo].[Person] AS [T1]",
29+
people_all_count = @"SELECT COUNT([T1].[ID])
2830
FROM [dbo].[Person] AS [T1]",
2931
people_equal = @"SELECT [T1].[ID], [T1].[FirstName], [T1].[MiddleInitial], [T1].[FamilyName], [T1].[FullName]
3032
FROM [dbo].[Person] AS [T1]
@@ -37,6 +39,7 @@ FROM [dbo].[Person] AS [T1]
3739
WHERE ([T1].[ID] < @id_1)";
3840

3941
Context.Database.Instance.AddCommandBehavior(people_all, cmd => People.ToDataTable());
42+
Context.Database.Instance.AddCommandBehavior(people_all_count, cmd => People.Count());
4043
Context.Database.Instance.AddCommandBehavior(people_greater_than, cmd => People.Where(x => x.ID > cmd.Parameters["@id_1"].GetValue<int>()).ToDataTable());
4144
Context.Database.Instance.AddCommandBehavior(people_equal, cmd => People.Where(x => x.ID == cmd.Parameters["@id_1"].GetValue<int>()).ToDataTable());
4245
Context.Database.Instance.AddCommandBehavior(people_less_than, cmd => People.Where(x => x.ID < cmd.Parameters["@id_1"].GetValue<int>()).ToDataTable());
@@ -46,7 +49,7 @@ FROM [dbo].[Person] AS [T1]
4649
public async Task ShouldBeAbleToGetSingleAsync()
4750
{
4851
Person person = await Context.People.Where(x => x.ID == 1)
49-
.AsAsyncSubSonicQueryable()
52+
.AsAsyncEnumerable()
5053
.SingleAsync();
5154

5255
person.ID.Should().Be(1);
@@ -58,7 +61,7 @@ public void ShouldBeAbleToThrowWhenSingleAsyncHasMoreThanOne()
5861
FluentActions.Invoking(async () =>
5962
{
6063
await Context.People.Where(x => x.ID > 0)
61-
.AsAsyncSubSonicQueryable()
64+
.AsAsyncEnumerable()
6265
.SingleAsync();
6366
}).Should().Throw<InvalidOperationException>();
6467
}
@@ -69,7 +72,7 @@ public void ShouldBeAbleToThrowSingleAsyncOnNull()
6972
FluentActions.Invoking(async () =>
7073
{
7174
await Context.People.Where(x => x.ID == -1)
72-
.AsAsyncSubSonicQueryable()
75+
.AsAsyncEnumerable()
7376
.SingleAsync();
7477
}).Should().Throw<InvalidOperationException>();
7578
}
@@ -78,7 +81,7 @@ await Context.People.Where(x => x.ID == -1)
7881
public async Task ShouldBeAbleToGetSingleOrDefaultAsync()
7982
{
8083
Person person = await Context.People.Where(x => x.ID == 1)
81-
.AsAsyncSubSonicQueryable()
84+
.AsAsyncEnumerable()
8285
.SingleOrDefaultAsync();
8386

8487
person.ID.Should().Be(1);
@@ -90,7 +93,7 @@ public void ShouldBeAbleToNotThrowSingleOrDefaultAsyncOnNull()
9093
FluentActions.Invoking(async () =>
9194
{
9295
Person person = await Context.People.Where(x => x.ID == -1)
93-
.AsAsyncSubSonicQueryable()
96+
.AsAsyncEnumerable()
9497
.SingleOrDefaultAsync();
9598

9699
person.Should().BeNull();
@@ -102,7 +105,7 @@ public void ShouldBeAbleToNotThrowSingleOrDefaultAsyncOnNull()
102105
public async Task ShouldBeAbleToGetFirstAsync()
103106
{
104107
Person person = await Context.People.Where(x => x.ID > 0)
105-
.AsAsyncSubSonicQueryable()
108+
.AsAsyncEnumerable()
106109
.FirstAsync();
107110

108111
person.ID.Should().Be(1);
@@ -114,7 +117,7 @@ public void ShouldBeAbleToThrowFirstAsyncOnNull()
114117
FluentActions.Invoking(async () =>
115118
{
116119
await Context.People.Where(x => x.ID < 1)
117-
.AsAsyncSubSonicQueryable()
120+
.AsAsyncEnumerable()
118121
.FirstAsync();
119122
}).Should().Throw<InvalidOperationException>();
120123
}
@@ -123,7 +126,7 @@ await Context.People.Where(x => x.ID < 1)
123126
public async Task ShouldBeAbleToGetFirstOrDefaultAsync()
124127
{
125128
Person person = await Context.People.Where(x => x.ID > 2)
126-
.AsAsyncSubSonicQueryable()
129+
.AsAsyncEnumerable()
127130
.FirstOrDefaultAsync();
128131

129132
person.ID.Should().Be(3);
@@ -135,7 +138,7 @@ public void ShouldBeAbleToNotThrowFirstOrDefaultAsyncOnNull()
135138
FluentActions.Invoking(async () =>
136139
{
137140
Person person = await Context.People.Where(x => x.ID < 1)
138-
.AsAsyncSubSonicQueryable()
141+
.AsAsyncEnumerable()
139142
.FirstOrDefaultAsync();
140143

141144
person.Should().BeNull();
@@ -150,13 +153,13 @@ public void ShouldBeAbleToLoadResultSet()
150153
{
151154
var cts = new CancellationTokenSource();
152155

153-
var people = Context.People
154-
.AsAsyncSubSonicQueryable()
156+
var people = await Context.People
157+
.AsAsyncEnumerable()
155158
.LoadAsync(cts.Token);
156159

157160
int cnt = 0;
158161

159-
await foreach(Person person in people.Result
162+
await foreach(Person person in people
160163
.WithCancellation(cts.Token)
161164
.ConfigureAwait(true))
162165
{
@@ -167,7 +170,7 @@ public void ShouldBeAbleToLoadResultSet()
167170
cnt++;
168171
}
169172

170-
cnt.Should().Be(Context.People.Count);
173+
cnt.Should().Be(Context.People.Count());
171174

172175
}).Should().NotThrow();
173176

SubSonic.Tests/DAL/Builders/DbWherePredicateBuilderTests.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ public GetPredicateFor(Expression<Func<TEntity, bool>> selector)
3939

4040
public Type Type => typeof(TEntity);
4141

42-
public Type DbSetType => typeof(DbSetCollection<>).MakeGenericType(Type);
42+
public Type DbSetType => typeof(ISubSonicDbSetCollection<>).MakeGenericType(Type);
4343

4444
public Expression Predicate { get; }
4545

@@ -77,7 +77,7 @@ public void ShouldBeAbleToGetWherePredicateBody()
7777

7878
where.Type.Should().Be(typeof(bool));
7979

80-
where.GetArgument(0).Type.Should().Be(@case.DbSetType);
80+
where.GetArgument(0).Type.GetInterface(@case.DbSetType.Name).Should().NotBeNull();
8181

8282
where.Expression.Should().NotBeNull();
8383
}

SubSonic.Tests/DAL/DbSetCollection/DbSetCollectionTests.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,12 +61,9 @@ public void CanAddNewInstanceToCollection()
6161

6262
Context.RealEstateProperties.Add(property);
6363

64-
IEntityProxy<RealEstateProperty> proxy = (IEntityProxy<RealEstateProperty>)Context.RealEstateProperties.AsEnumerable().ElementAt(0);
64+
IEntityProxy<RealEstateProperty> proxy = Context.ChangeTracking.GetCacheFor<RealEstateProperty>().Single(x => x.IsNew);
6565

66-
proxy.IsNew.Should().BeTrue();
67-
proxy.Data.HasParallelPowerGeneration.Should().Be(property.HasParallelPowerGeneration);
68-
proxy.Data.StatusID.Should().Be(property.StatusID);
69-
property.Should().BeEquivalentTo(proxy.Data);
66+
proxy.Data.Should().BeEquivalentTo(property);
7067
}
7168

7269
[Test]

SubSonic.Tests/DAL/SUT/MochClassDefinitions/TestDbContext.cs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Microsoft.Extensions.Logging;
2+
using SubSonic.Collections;
23
using SubSonic.Extensions;
34
using SubSonic.Extensions.Test;
45
using SubSonic.Extensions.Test.NUnit;
@@ -16,15 +17,15 @@ public TestDbContext()
1617

1718
}
1819

19-
public DbSetCollection<Models.RealEstateProperty> RealEstateProperties { get; private set; }
20+
public ISubSonicDbSetCollection<Models.RealEstateProperty> RealEstateProperties { get; private set; }
2021

21-
public DbSetCollection<Models.Status> Statuses { get; private set; }
22+
public ISubSonicDbSetCollection<Models.Status> Statuses { get; private set; }
2223

23-
public DbSetCollection<Models.Unit> Units { get; private set; }
24+
public ISubSonicDbSetCollection<Models.Unit> Units { get; private set; }
2425

25-
public DbSetCollection<Models.Renter> Renters { get; private set; }
26+
public ISubSonicDbSetCollection<Models.Renter> Renters { get; private set; }
2627

27-
public DbSetCollection<Models.Person> People { get; private set; }
28+
public ISubSonicDbSetCollection<Models.Person> People { get; private set; }
2829

2930
protected override void OnDbConfiguring(DbContextOptionsBuilder config)
3031
{

SubSonic/Data/ChangeTracking/ChangeTrackerElement.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99

1010
namespace SubSonic.Data.Caching
1111
{
12+
using Collections;
1213
using Infrastructure;
1314
using Infrastructure.Logging;
1415
using Infrastructure.Schema;

SubSonic/DbContext/DbContext.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
using SubSonic.Infrastructure;
33
using System;
44
using System.Reflection;
5-
using System.Resources;
65
using System.Runtime.CompilerServices;
76

87
[assembly: InternalsVisibleTo("SubSonic.Extensions.Test", AllInternalsVisible = true)]
@@ -11,7 +10,9 @@
1110

1211
namespace SubSonic
1312
{
13+
using Collections;
1414
using Linq;
15+
1516
public partial class DbContext
1617
: IDisposable, IInfrastructure<IServiceProvider>
1718
{
@@ -36,7 +37,7 @@ private void SetDbSetCollections()
3637
{
3738
foreach(PropertyInfo info in GetType().GetProperties())
3839
{
39-
if(!info.PropertyType.IsGenericType || info.PropertyType.GetGenericTypeDefinition() != typeof(DbSetCollection<>))
40+
if(!info.PropertyType.IsGenericType || info.PropertyType.GetGenericTypeDefinition() != typeof(ISubSonicDbSetCollection<>))
4041
{
4142
continue;
4243
}

SubSonic/Extensions/Internal/Type.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ public static bool IsEnumerable(this Type type)
5959
return type.GetInterface(typeof(IEnumerable).FullName).IsNotNull();
6060
}
6161

62+
public static bool IsAsyncEnumerable(this Type type)
63+
{
64+
return type.IsGenericType && type.IsAssignableFrom(typeof(IAsyncEnumerable<>).MakeGenericType(type.GenericTypeArguments));
65+
}
66+
6267
public static bool IsNullableType(this Type type)
6368
{
6469
return (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>));

SubSonic/Infrastructure/Builders/DbSqlQueryBuilder/DbSqlQueryBuilder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
namespace SubSonic.Infrastructure.Builders
88
{
9+
using Collections;
910
using Linq;
1011
using Linq.Expressions;
1112
using Logging;

SubSonic/Infrastructure/Builders/DbSqlQueryBuilder/DbSqlQueryBuilderAsyncQueryProvider.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,10 @@ await Scope.Connection.CloseAsync()
8282
}
8383
else if (expression is MethodCallExpression call)
8484
{
85-
if (!call.Type.GenericTypeArguments[0].IsEnumerable())
85+
Type callType = call.Type.GenericTypeArguments[0];
86+
87+
if (!(callType.IsEnumerable() ||
88+
callType.IsAsyncEnumerable()))
8689
{
8790
IEnumerable<TResult> result = await ExecuteAsync<IEnumerable<TResult>>(BuildSelect(call), cancellationToken).ConfigureAwait(true);
8891

SubSonic/Infrastructure/Builders/DbSqlQueryBuilder/DbSqlQueryBuilderQueryProvider.cs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,18 @@
1-
using System;
2-
using System.Linq;
3-
using System.Linq.Expressions;
4-
using System.Collections;
1+
using Microsoft.Extensions.Logging;
2+
using System;
53
using System.Collections.Generic;
64
using System.ComponentModel;
75
using System.Data;
86
using System.Data.Common;
9-
using System.Globalization;
10-
using Microsoft.Extensions.Logging;
7+
using System.Linq;
8+
using System.Linq.Expressions;
119

1210
namespace SubSonic.Infrastructure.Builders
1311
{
14-
using Logging;
12+
using Collections;
13+
using Linq;
1514
using Linq.Expressions;
16-
using System.Threading.Tasks;
17-
using SubSonic.Linq;
15+
using Logging;
1816

1917
public partial class DbSqlQueryBuilder
2018
{

0 commit comments

Comments
 (0)