Skip to content

Commit d22ca23

Browse files
committed
#29 interesting behavior. apparently netstandard 2.0 has limited support for async db ops. it will be really available in netstandard 2.1
1 parent e1578b0 commit d22ca23

File tree

11 files changed

+285
-28
lines changed

11 files changed

+285
-28
lines changed

SubSonic.Extensions.Test/MockDbClient/MockDbCommand.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,9 @@ protected override DbDataReader ExecuteDbDataReader(System.Data.CommandBehavior
120120
}
121121
}
122122

123-
protected override Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
123+
protected override async Task<DbDataReader> ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
124124
{
125-
126-
return Task.Run(() => ExecuteDbDataReader(behavior), cancellationToken);
125+
return ExecuteDbDataReader(behavior);
127126
}
128127

129128
public override int ExecuteNonQuery()

SubSonic.Extensions.Test/MockDbClient/MockDbDataReaderCollection.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ public override int GetValues(object[] values)
149149

150150
public override bool HasRows
151151
{
152-
get { return inner.HasRows; }
152+
get { return inner?.HasRows ?? false; }
153153
}
154154

155155
public override bool IsClosed

SubSonic.Tests/DAL/Asynchronous/AsynchronousTests.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,13 @@ public override void SetupTestFixture()
2626
string
2727
people_equal = @"SELECT [T1].[ID], [T1].[FirstName], [T1].[MiddleInitial], [T1].[FamilyName], [T1].[FullName]
2828
FROM [dbo].[Person] AS [T1]
29-
WHERE ([T1].[ID] == @id_1)",
29+
WHERE ([T1].[ID] = @id_1)",
3030
people_greater_than = @"SELECT [T1].[ID], [T1].[FirstName], [T1].[MiddleInitial], [T1].[FamilyName], [T1].[FullName]
3131
FROM [dbo].[Person] AS [T1]
3232
WHERE ([T1].[ID] > @id_1)",
3333
people_less_than = @"SELECT [T1].[ID], [T1].[FirstName], [T1].[MiddleInitial], [T1].[FamilyName], [T1].[FullName]
3434
FROM [dbo].[Person] AS [T1]
35-
WHERE ([T1].[ID] > @id_1)";
35+
WHERE ([T1].[ID] < @id_1)";
3636

3737
Context.Database.Instance.AddCommandBehavior(people_greater_than, cmd => People.Where(x => x.ID > cmd.Parameters["@id_1"].GetValue<int>()).ToDataTable());
3838
Context.Database.Instance.AddCommandBehavior(people_equal, cmd => People.Where(x => x.ID == cmd.Parameters["@id_1"].GetValue<int>()).ToDataTable());
@@ -96,11 +96,11 @@ public void ShouldBeAbleToNotThrowSingleOrDefaultAsyncOnNull()
9696
}
9797

9898
[Test]
99-
public async Task ShouldBeAbleToGetFirstAsync(CancellationToken cancellationToken)
99+
public async Task ShouldBeAbleToGetFirstAsync()
100100
{
101101
Person person = await Context.People.Where(x => x.ID > 0)
102102
.AsAsyncSubSonicQueryable()
103-
.FirstAsync(cancellationToken);
103+
.FirstAsync();
104104

105105
person.ID.Should().Be(1);
106106
}
@@ -141,7 +141,7 @@ public void ShouldBeAbleToNotThrowFirstOrDefaultAsyncOnNull()
141141
}
142142

143143
[Test]
144-
public async Task ShouldBeAbleToLoadResultSet()
144+
public void ShouldBeAbleToLoadResultSet()
145145
{
146146
FluentActions.Invoking(async () =>
147147
{

SubSonic/Infrastructure/Builders/DbSqlQueryBuilder/DbSqlQueryBuilderAsyncQueryProvider.cs

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1-
using System.Linq.Expressions;
1+
using System;
2+
using System.Linq.Expressions;
23
using System.Threading;
34
using System.Threading.Tasks;
45

56
namespace SubSonic.Infrastructure.Builders
67
{
8+
using Linq;
9+
using Linq.Expressions;
10+
using System.Data.Common;
11+
712
public partial class DbSqlQueryBuilder
813
{
914
public async Task<TResult> ExecuteAsync<TResult>(Expression expression, CancellationToken cancellationToken)
@@ -13,7 +18,78 @@ public async Task<TResult> ExecuteAsync<TResult>(Expression expression, Cancella
1318
throw Error.ArgumentNull(nameof(expression));
1419
}
1520

16-
throw Error.NotImplemented();
21+
TResult result = default(TResult);
22+
23+
if (expression is DbExpression query)
24+
{
25+
using (SharedDbConnectionScope Scope = DbContext.ServiceProvider.GetService<SharedDbConnectionScope>())
26+
{
27+
IDbQuery dbQuery = ToQuery(query);
28+
29+
try
30+
{
31+
await Scope.Connection.OpenAsync(cancellationToken)
32+
.ConfigureAwait(false);
33+
34+
Type elementType = query.Type.GetQualifiedType();
35+
36+
bool isEntityModel = DbContext.DbModel.IsEntityModelRegistered(elementType);
37+
38+
if (isEntityModel)
39+
{
40+
using (DbDataReader reader = await Scope.Database
41+
.ExecuteReaderAsync(dbQuery, cancellationToken)
42+
.ConfigureAwait(false))
43+
{
44+
if (reader.HasRows)
45+
{
46+
while (await reader.ReadAsync().ConfigureAwait(false))
47+
{
48+
DbContext.Current.ChangeTracking.Add(elementType, reader.ActivateAndLoadInstanceOf(elementType));
49+
}
50+
}
51+
}
52+
53+
result = DbContext.Current.ChangeTracking.Where<TResult>(elementType, this, query);
54+
}
55+
else
56+
{
57+
if (await Scope.Database.ExecuteScalarAsync(dbQuery, cancellationToken)
58+
.ConfigureAwait(false) is TResult scalar)
59+
{
60+
result = scalar;
61+
}
62+
}
63+
}
64+
finally
65+
{
66+
dbQuery.CleanUpParameters();
67+
68+
if (!(Scope.Connection is null))
69+
{
70+
#if NETSTANDARD2_1
71+
await Scope.Connection.CloseAsync()
72+
.ConfigureAwait(false);
73+
#elif NETSTANDARD2_0
74+
Scope.Connection.Close();
75+
#endif
76+
}
77+
}
78+
}
79+
}
80+
else if (expression is MethodCallExpression call)
81+
{
82+
result = await ExecuteAsync<TResult>(BuildSelect(call), cancellationToken).ConfigureAwait(true);
83+
}
84+
85+
if (result is TResult success)
86+
{
87+
return success;
88+
}
89+
else
90+
{
91+
throw Error.NotImplemented();
92+
}
1793
}
1894

1995
public async Task<object> ExecuteAsync(Expression expression, CancellationToken cancellationToken)

SubSonic/Infrastructure/Builders/DbSqlQueryBuilder/DbSqlQueryBuilderBuildMethods.cs

Lines changed: 95 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ namespace SubSonic.Infrastructure.Builders
1313
using Infrastructure.Schema;
1414
using SysLinq = System.Linq;
1515
using System.Diagnostics;
16+
using System.Net.Security;
1617

1718
public partial class DbSqlQueryBuilder
1819
{
@@ -23,11 +24,101 @@ public partial class DbSqlQueryBuilder
2324
#endregion
2425

2526
#region Build Select
27+
public Expression BuildSelect(MethodCallExpression call)
28+
{
29+
if (!(call is null))
30+
{
31+
DbExpression query = null;
32+
LambdaExpression
33+
predicate = null,
34+
predicate1 = null,
35+
predicate2 = null;
36+
37+
foreach(Expression argument in call.Arguments)
38+
{
39+
if (argument is DbExpression _query)
40+
{
41+
query = _query;
42+
}
43+
else if (argument is UnaryExpression _unary)
44+
{
45+
if (_unary.Operand is LambdaExpression _predicate)
46+
{
47+
predicate2 = _predicate;
48+
}
49+
}
50+
}
51+
52+
MethodInfo method = null;
53+
54+
if (query is DbSelectExpression _select)
55+
{
56+
predicate1 = GetPredicateFromWhere(_select.Where, out method);
57+
}
58+
else if (query is DbSelectPageExpression _paged)
59+
{
60+
predicate1 = GetPredicateFromWhere(_paged.Select.Where, out method);
61+
}
62+
63+
if (!(predicate1 is null) && !(predicate2 is null))
64+
{
65+
predicate = Expression.Lambda(
66+
predicate1.Type,
67+
Expression.AndAlso(predicate1.Body, predicate2.Body),
68+
predicate1.Parameters.ToArray());
69+
}
70+
else
71+
{
72+
predicate = predicate1 ?? predicate2;
73+
}
74+
75+
method = method ?? typeof(Queryable).GetGenericMethod(nameof(Queryable.Where), new[] { DbTable.Type, predicate.GetType() });
76+
77+
if (query is DbSelectExpression select)
78+
{
79+
return DbExpression.DbSelect(select,
80+
DbWherePredicateBuilder.GetWhereTranslation(
81+
DbExpression.DbWhere(method, new Expression[] { query, predicate })));
82+
}
83+
else if (query is DbSelectPageExpression paged)
84+
{
85+
return DbExpression.DbPagedSelect(
86+
DbExpression.DbSelect(paged.Select,
87+
DbWherePredicateBuilder.GetWhereTranslation(
88+
DbExpression.DbWhere(method, new Expression[] { query, predicate }))),
89+
paged.PageNumber, paged.PageSize);
90+
}
91+
else
92+
{
93+
throw Error.NotImplemented();
94+
}
95+
}
96+
97+
return call;
98+
}
99+
100+
private LambdaExpression GetPredicateFromWhere(Expression where, out MethodInfo method)
101+
{
102+
method = null;
103+
104+
if (where is DbWhereExpression _where)
105+
{
106+
method = _where.Method;
107+
108+
if (_where.GetArgument(1) is LambdaExpression predicate)
109+
{
110+
return predicate;
111+
}
112+
}
113+
114+
return null;
115+
}
116+
26117
public Expression BuildSelect(Expression select, Expression where)
27118
{
28119
if (select is DbSelectExpression _select)
29120
{
30-
return new DbSelectExpression(_select.QueryObject, _select.Type, _select.From, _select.Columns, where ?? _select.Where, _select.OrderBy, _select.GroupBy, _select.IsDistinct, _select.Take, _select.Skip);
121+
return new DbSelectExpression(_select.QueryObject, _select.Type, _select.From, _select.Columns, where ?? _select.Where, _select.OrderBy, _select.GroupBy, _select.IsDistinct, _select.Take, _select.Skip, _select.IsCte);
31122
}
32123

33124
throw new NotSupportedException();
@@ -37,7 +128,7 @@ public Expression BuildSelect(Expression expression, bool isDistinct)
37128
{
38129
if (expression is DbSelectExpression select)
39130
{
40-
return new DbSelectExpression(select.QueryObject, select.Type, select.From, select.Columns, select.Where, select.OrderBy, select.GroupBy, isDistinct, select.Take, select.Skip);
131+
return new DbSelectExpression(select.QueryObject, select.Type, select.From, select.Columns, select.Where, select.OrderBy, select.GroupBy, isDistinct, select.Take, select.Skip, select.IsCte);
41132
}
42133

43134
throw new NotSupportedException();
@@ -71,7 +162,7 @@ public Expression BuildSelect(Expression expression, IDbEntityProperty property)
71162
typeof(SysLinq.IQueryable<>).MakeGenericType(property.PropertyType),
72163
select.From,
73164
select.Columns.Where(x => x.PropertyName.Equals(property.PropertyName, StringComparison.CurrentCulture)),
74-
select.Where, select.OrderBy, select.GroupBy, select.IsDistinct, select.Take, select.Skip);
165+
select.Where, select.OrderBy, select.GroupBy, select.IsDistinct, select.Take, select.Skip, select.IsCte);
75166
}
76167

77168
throw new NotSupportedException();
@@ -81,7 +172,7 @@ private Expression BuildSelect(Expression expression, IEnumerable<DbColumnDeclar
81172
{
82173
if (expression is DbSelectExpression select)
83174
{
84-
return new DbSelectExpression(select.QueryObject, select.Type, select.From, columns, select.Where, select.OrderBy, select.GroupBy, select.IsDistinct, select.Take, select.Skip);
175+
return new DbSelectExpression(select.QueryObject, select.Type, select.From, columns, select.Where, select.OrderBy, select.GroupBy, select.IsDistinct, select.Take, select.Skip, select.IsCte);
85176
}
86177

87178
return expression;

SubSonic/Infrastructure/Builders/DbSqlQueryBuilder/DbSqlQueryBuilderQueryProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ public object Execute(Expression expression)
180180

181181
if (expression is DbExpression query)
182182
{
183-
using (SharedDbConnectionScope Scope = DbContext.ServiceProvider.GetService<SharedDbConnectionScope>())
183+
using (AutomaticConnectionScope Scope = DbContext.ServiceProvider.GetService<AutomaticConnectionScope>())
184184
{
185185
IDbQuery dbQuery = ToQuery(query);
186186

SubSonic/Infrastructure/Builders/DbSqlTableTypeProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ public Expression BuildSelect(Expression expression, IDbEntityProperty property)
9292
typeof(IQueryable<>).MakeGenericType(property.PropertyType),
9393
select.From,
9494
select.Columns.Where(x => x.PropertyName.Equals(property.PropertyName, StringComparison.CurrentCulture)),
95-
select.Where, select.OrderBy, select.GroupBy, select.IsDistinct, select.Take, select.Skip);
95+
select.Where, select.OrderBy, select.GroupBy, select.IsDistinct, select.Take, select.Skip, select.IsCte);
9696
}
9797

9898
throw new NotSupportedException();

0 commit comments

Comments
 (0)