Skip to content

Commit a309da4

Browse files
committed
#27 I have all unit test passing
1 parent 329eed6 commit a309da4

File tree

21 files changed

+385
-209
lines changed

21 files changed

+385
-209
lines changed

SubSonic.Tests/DAL/Builders/DbWherePredicateBuilderTests.cs

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,19 +14,23 @@ namespace SubSonic.Tests.DAL.Builders
1414
using Linq.Expressions;
1515
using Infrastructure.Builders;
1616
using Models = Extensions.Test.Models;
17-
17+
using System.Reflection;
18+
using SubSonic.Infrastructure;
19+
1820
[TestFixture]
1921
public class DbWherePredicateBuilderTests
2022
: SUT.BaseTestFixture
2123
{
2224
interface IPredicateTestCase
2325
{
24-
LambdaExpression Predicate { get; }
26+
Expression Predicate { get; }
2527
Type Type { get; }
26-
DbTableExpression Table { get; }
28+
Type DbSetType { get; }
29+
Expression Expression { get; }
2730
}
2831
class GetPredicateFor<TEntity>
2932
: IPredicateTestCase
33+
where TEntity : class
3034
{
3135
public GetPredicateFor(Expression<Func<TEntity, bool>> selector)
3236
{
@@ -35,9 +39,21 @@ public GetPredicateFor(Expression<Func<TEntity, bool>> selector)
3539

3640
public Type Type => typeof(TEntity);
3741

38-
public LambdaExpression Predicate { get; }
42+
public Type DbSetType => typeof(DbSetCollection<>).MakeGenericType(Type);
43+
44+
public Expression Predicate { get; }
3945

40-
public DbTableExpression Table => DbContext.DbModel.GetEntityModel<TEntity>().Table;
46+
public Expression Expression
47+
{
48+
get
49+
{
50+
MethodInfo method = typeof(Queryable).GetGenericMethod(nameof(Queryable.Where), new[] { DbSetType, Predicate.GetType() });
51+
52+
return DbExpression.DbWhere(method, new[] {
53+
DbContext.Current.Set<TEntity>()?.Expression,
54+
Predicate });
55+
}
56+
}
4157
}
4258

4359
private static IEnumerable<IPredicateTestCase> Expressions()
@@ -50,14 +66,25 @@ private static IEnumerable<IPredicateTestCase> Expressions()
5066
[Test]
5167
public void ShouldBeAbleToGetWherePredicateBody()
5268
{
53-
//foreach(IPredicateTestCase @case in Expressions())
54-
Parallel.ForEach(Expressions(), @case =>
69+
foreach(IPredicateTestCase @case in Expressions())
70+
//Parallel.ForEach(Expressions(), @case =>
5571
{
56-
var result = DbWherePredicateBuilder.GetWherePredicate(@case.Type, @case.Predicate, DbExpressionType.Where, @case.Table);
72+
var result = DbWherePredicateBuilder.GetWhereTranslation(@case.Expression);
73+
74+
if (result is DbWhereExpression where)
75+
{
76+
where.Parameters.Count.Should().NotBe(0);
77+
78+
where.Type.Should().Be(typeof(bool));
79+
80+
where.GetArgument(0).Type.Should().Be(@case.DbSetType);
81+
82+
where.Expression.Should().NotBeNull();
83+
}
5784

5885
result.Should().NotBeNull();
5986
}
60-
);
87+
//);
6188
}
6289
}
6390
}

SubSonic.Tests/DAL/SqlQueryProvider/SqlGeneratorTests.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -477,11 +477,11 @@ FROM [dbo].[Unit] AS [{1}]
477477
public void CanMergeMultipleWhereStatements()
478478
{
479479
string
480-
units =
480+
units_sql =
481481
@"SELECT [{0}].[ID], [{0}].[Bedrooms] AS [NumberOfBedrooms], [{0}].[StatusID], [{0}].[RealEstatePropertyID]
482482
FROM [dbo].[Unit] AS [{0}]
483483
WHERE ([{0}].[RealEstatePropertyID] = 1)".Format("T1"),
484-
status =
484+
status_sql =
485485
@"SELECT [{0}].[ID], [{0}].[Bedrooms] AS [NumberOfBedrooms], [{0}].[StatusID], [{0}].[RealEstatePropertyID]
486486
FROM [dbo].[Unit] AS [{0}]
487487
WHERE (([{0}].[RealEstatePropertyID] = 1) AND ([{0}].[StatusID] = 1))".Format("T1"),
@@ -496,14 +496,18 @@ FROM [dbo].[Unit] AS [{0}]
496496
instance.StatusID = 1;
497497

498498
Context.Database.Instance.AddCommandBehavior(
499-
units,
499+
units_sql,
500500
Units.Where(x => x.RealEstatePropertyID == 1));
501501

502502
Context.Database.Instance.AddCommandBehavior(
503-
status,
503+
status_sql,
504504
Units.Where(x => x.RealEstatePropertyID == 1 && x.StatusID == 1));
505505

506-
Expression select = ((ISubSonicCollection<Unit>)instance.Units.Where(Unit => Unit.StatusID == 1)).Expression;
506+
IQueryable<Unit> units = instance.Units
507+
.AsQueryable()
508+
.Where(Unit => Unit.StatusID == 1);
509+
510+
Expression select = units.Expression;
507511

508512
select.Should().NotBeNull();
509513

SubSonic/Data/ChangeTracking/ChangeTrackerElement.cs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,10 @@ public override int Count(Expression expression)
8080
return 0;
8181
}
8282

83-
results = results.Where(((Expression<Func<TEntity, bool>>)where.LambdaPredicate).Compile());
83+
if (where.GetArgument(1) is Expression<Func<TEntity, bool>> predicate)
84+
{
85+
results = results.Where(predicate.Compile());
86+
}
8487
}
8588

8689
return results.Count();
@@ -285,7 +288,10 @@ public override TResult Where<TResult>(IQueryProvider provider, Expression expre
285288

286289
if (select.Where is DbWhereExpression where)
287290
{
288-
results = results.Where(((Expression<Func<TEntity, bool>>)where.LambdaPredicate).Compile());
291+
if (where.GetArgument(1) is Expression<Func<TEntity, bool>> predicate)
292+
{
293+
results = results.Where(predicate.Compile());
294+
}
289295
}
290296

291297
if (typeof(TResult).IsEnumerable())

SubSonic/Extensions/Internal/Expressions.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ namespace SubSonic
88

99
internal static partial class InternalExtensions
1010
{
11+
public static Func<TSource, bool> CombinePredicates<TSource>(Func<TSource, bool> predicate1, Func<TSource, bool> predicate2) =>
12+
(x) => predicate1(x) && predicate2(x);
13+
1114
public static Expression ReBuild(this Expression expression, ParameterExpression parameter)
1215
{
1316
if (expression is BinaryExpression binary)

SubSonic/Extensions/Internal/Type.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,15 +200,25 @@ public static MethodInfo GetGenericMethod(this Type type, string name, Type[] ty
200200
{
201201
if (info.IsGenericMethod)
202202
{
203-
MethodInfo test = info.MakeGenericMethod(types[0]);
203+
MethodInfo test = null;
204+
205+
if (types[0].IsGenericType)
206+
{
207+
test = info.MakeGenericMethod(types[0].GenericTypeArguments[0]);
208+
}
209+
else
210+
{
211+
test = info.MakeGenericMethod(types[0]);
212+
}
204213

205214
bool match = true;
206215

207216
ParameterInfo[] parameters = test.GetParameters();
208217

209218
for (int i = 0, cnt = types.Length; i < cnt; i++)
210219
{
211-
match &= parameters[i].ParameterType == types[i];
220+
match &= parameters[i].ParameterType.IsAssignableFrom(types[i]) ||
221+
types[i].IsAssignableFrom(parameters[i].ParameterType);
212222
}
213223

214224
if (match)

SubSonic/Infrastructure/Builders/DbSqlQueryBuilder/DbSqlQueryBuilder.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,13 @@ private Expression BuildDeleteQuery<TEntity>(IEnumerable<TEntity> entities)
150150

151151
predicate = (LambdaExpression)BuildLambda(logical, LambdaType.Predicate);
152152

153+
MethodInfo method = typeof(Queryable).GetGenericMethod(nameof(Queryable.Where), new[] { DbTable.Type, predicate.GetType() });
154+
153155
return DbExpression.DbDelete(
154156
entities,
155157
DbTable,
156-
DbExpression.DbWhere(DbTable, DbEntity.EntityModelType, predicate));
158+
DbWherePredicateBuilder.GetWhereTranslation(
159+
DbExpression.DbWhere(method, new Expression[] { DbTable, predicate })));
157160
}
158161

159162
protected virtual DbSqlQueryType GetQueryType(Expression expression)

SubSonic/Infrastructure/Builders/DbSqlQueryBuilder/DbSqlQueryBuilderBuildMethods.cs

Lines changed: 65 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ namespace SubSonic.Infrastructure.Builders
1212
using Linq.Expressions;
1313
using Infrastructure.Schema;
1414
using SysLinq = System.Linq;
15+
using System.Diagnostics;
1516

1617
public partial class DbSqlQueryBuilder
1718
{
@@ -145,6 +146,24 @@ private Expression BuildSelect(Expression expression, IEnumerable<DbColumnDeclar
145146
#endregion
146147

147148
#region Build Where
149+
public Expression BuildWhere(DbExpression expression, LambdaExpression predicate)
150+
{
151+
if (expression is null)
152+
{
153+
throw Error.ArgumentNull(nameof(expression));
154+
}
155+
156+
if (predicate is null)
157+
{
158+
throw Error.ArgumentNull(nameof(predicate));
159+
}
160+
161+
MethodInfo method = typeof(Queryable).GetGenericMethod(nameof(Queryable.Where), new[] { expression.Type, predicate.GetType() });
162+
163+
return DbWherePredicateBuilder.GetWhereTranslation(
164+
DbExpression.DbWhere(method, new Expression[] { expression, predicate }));
165+
}
166+
148167
public Expression BuildWhere(DbTableExpression table, Expression where, Type type, LambdaExpression predicate)
149168
{
150169
if (where.IsNotNull())
@@ -158,38 +177,39 @@ public Expression BuildWhere(DbTableExpression table, Expression where, Type typ
158177
where is DbWhereExpression _where)
159178
{
160179
Expression
161-
logical = DbWherePredicateBuilder.GetBodyExpression(_where.LambdaPredicate.Body, predicate.Body, DbGroupOperator.AndAlso);
180+
logical = DbWherePredicateBuilder.GetBodyExpression(_where.GetArgument(1), predicate.Body, DbGroupOperator.AndAlso);
162181
predicate = BuildLambda(logical, LambdaType.Predicate) as LambdaExpression;
163182
}
164183
else
165184
{
166185
throw new NotSupportedException();
167186
}
168187
}
169-
return DbExpression.DbWhere(table, type, predicate);
188+
189+
throw Error.NotImplemented();
170190
}
171191

172-
public Expression BuildWhere(DbTableExpression table, Expression where, Type type, Expression predicate)
173-
{
174-
LambdaExpression lambda = null;
192+
//public Expression BuildWhere(DbTableExpression table, Expression where, Type type, Expression predicate)
193+
//{
194+
// LambdaExpression lambda = null;
175195

176-
if (predicate is UnaryExpression unary)
177-
{
178-
if (unary.Operand is LambdaExpression _unary)
179-
{
180-
lambda = _unary;
181-
}
182-
}
196+
// if (predicate is UnaryExpression unary)
197+
// {
198+
// if (unary.Operand is LambdaExpression _unary)
199+
// {
200+
// lambda = _unary;
201+
// }
202+
// }
183203

184-
return BuildWhere(table, where, type, lambda);
185-
}
204+
// return BuildWhere(table, where, type, lambda);
205+
//}
186206

187207
public Expression BuildWherePredicate(Expression collection, Expression lambda)
188208
{
189209
return BuildCall("Where", collection, lambda);
190210
}
191211

192-
public Expression BuildWhereFindByIDPredicate(DbTableExpression dbTable, object[] keyData, params string[] keyNames)
212+
public Expression BuildWhereFindByIDPredicate(DbExpression expression, object[] keyData, params string[] keyNames)
193213
{
194214
if (keyData.IsNull())
195215
{
@@ -206,16 +226,7 @@ public Expression BuildWhereFindByIDPredicate(DbTableExpression dbTable, object[
206226

207227
LambdaExpression predicate = (LambdaExpression)BuildLambda(logical, LambdaType.Predicate);
208228

209-
return BuildWhere(dbTable, null, DbEntity.EntityModelType, predicate);
210-
}
211-
212-
public Expression BuildWhereExists<TEntity>(DbTableExpression from, Type type, Expression<Func<TEntity, System.Linq.IQueryable>> select)
213-
{
214-
return DbExpression.DbWhere(from, type, select, DbExpressionType.Exists);
215-
}
216-
public Expression BuildWhereNotExists<TEntity>(DbTableExpression from, Type type, Expression<Func<TEntity, System.Linq.IQueryable>> select)
217-
{
218-
return DbExpression.DbWhere(from, type, select, DbExpressionType.NotExists);
229+
return BuildWhere(expression, predicate);
219230
}
220231
#endregion
221232

@@ -252,27 +263,31 @@ public Expression BuildCall(string nameofCallee, Expression collection, Expressi
252263
public Expression BuildLambda(Expression body, LambdaType @call, params string[] properties)
253264
{
254265
Expression result;
266+
255267
switch (call)
256268
{
257269
case Infrastructure.LambdaType.Predicate:
258270
{
259-
Type fnType = Expression.GetFuncType(Parameter.Type, typeof(bool));
271+
if (body is null)
272+
{
273+
throw Error.ArgumentNull(nameof(body));
274+
}
260275

261-
result = Expression.Lambda(fnType, body, Parameter);
276+
return Expression.Lambda(
277+
Expression.GetFuncType(Parameter.Type, body.Type),
278+
body,
279+
Parameter);
262280
}
263-
break;
264281
case Infrastructure.LambdaType.Selector:
265282
{
266283
PropertyInfo info = Parameter.Type.GetProperty(properties[0]);
267284
Expression property = Expression.Property(Parameter, info);
268285

269-
result = Expression.Lambda(Expression.GetFuncType(Parameter.Type, info.PropertyType), property, Parameter);
286+
return Expression.Lambda(Expression.GetFuncType(Parameter.Type, info.PropertyType), property, Parameter);
270287
}
271-
break;
272288
default:
273289
throw new NotImplementedException();
274290
}
275-
return result;
276291
}
277292

278293
public Expression BuildLogicalIn(Expression body, PropertyInfo property, SysLinq.IQueryable queryable, DbGroupOperator @group)
@@ -665,16 +680,32 @@ private Expression BuildSelectWithWhere(MethodCallExpression expression)
665680
}
666681
else if (argument is UnaryExpression unary)
667682
{
668-
if (unary.Operand is LambdaExpression _unary)
683+
if (unary.Operand is LambdaExpression predicate)
669684
{
670-
where = _unary;
685+
if (select.Where is DbWhereExpression existing)
686+
{
687+
if (existing.GetArgument(1) is LambdaExpression predicate2)
688+
{
689+
Expression
690+
body = Expression.AndAlso(predicate2.Body, predicate.Body);
691+
692+
where = Expression.Lambda(predicate2.Type, body, predicate2.Parameters.ToArray());
693+
}
694+
}
695+
else
696+
{
697+
where = predicate;
698+
}
671699
}
672700
}
673701
}
674702

703+
MethodInfo method = typeof(Queryable).GetGenericMethod(nameof(Queryable.Where), new[] { select.Type, where.GetType() });
704+
675705
return DbExpression.DbSelect(
676706
select,
677-
DbExpression.DbWhere(select.From, select.Type, where));
707+
DbWherePredicateBuilder.GetWhereTranslation(
708+
DbExpression.DbWhere(method, new Expression[] { select, where })));
678709
}
679710

680711
return expression;

SubSonic/Infrastructure/Builders/DbSqlQueryBuilder/DbSqlQueryBuilderQueryProvider.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,10 @@ public TResult Execute<TResult>(Expression expression)
111111
}
112112
else if (call.Arguments[i] is UnaryExpression unary)
113113
{
114-
where = BuildWhere(dbSelect.From, dbSelect.Where, dbSelect.Type, unary);
114+
if (unary.Operand is LambdaExpression lambda)
115+
{
116+
where = BuildWhere(dbSelect, lambda);
117+
}
115118
}
116119
}
117120

SubSonic/Infrastructure/Builders/DbSqlTableTypeProvider.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ public Expression BuildWherePredicate(Expression collection, Expression logical)
156156
throw new NotImplementedException();
157157
}
158158

159-
public Expression BuildWhereFindByIDPredicate(DbTableExpression from, object[] keyData, params string[] keyNames)
159+
public Expression BuildWhereFindByIDPredicate(DbExpression expression, object[] keyData, params string[] keyNames)
160160
{
161161
throw new NotImplementedException();
162162
}

0 commit comments

Comments
 (0)