Skip to content

Commit 09d5000

Browse files
authored
Merge pull request #42 from SubSonic-Core/dev/41-min-max-sum-average
Dev/41 min max sum average
2 parents 577a596 + 328ce0c commit 09d5000

File tree

3 files changed

+87
-9
lines changed

3 files changed

+87
-9
lines changed

SubSonic.Tests/DAL/ExtensionMethod/ExtensionMethodTests.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,36 @@
1010

1111
namespace SubSonic.Tests.DAL.ExtensionMethod
1212
{
13+
using Extensions.Test;
14+
using SubSonic.Extensions.Test.Models;
15+
1316
[TestFixture]
1417
public class ExtensionMethodTests
1518
: BaseTestFixture
1619
{
20+
protected override void SetSelectBehaviors()
21+
{
22+
base.SetSelectBehaviors();
23+
24+
string
25+
person_min = @"SELECT MIN([T1].[ID])
26+
FROM [dbo].[Person] AS [T1]",
27+
person_max = @"SELECT MAX([T1].[ID])
28+
FROM [dbo].[Person] AS [T1]",
29+
renter_sum = @"SELECT SUM([T1].[Rent])
30+
FROM [dbo].[Renter] AS [T1]
31+
WHERE ([T1].[PersonID] = @personid_1)",
32+
renter_avg = @"SELECT AVG([T1].[Rent])
33+
FROM [dbo].[Renter] AS [T1]
34+
WHERE ([T1].[PersonID] = @personid_1)";
35+
36+
Context.Database.Instance.AddCommandBehavior(person_max, cmd => People.Max(x => x.ID));
37+
Context.Database.Instance.AddCommandBehavior(person_min, cmd => People.Min(x => x.ID));
38+
Context.Database.Instance.AddCommandBehavior(renter_sum, cmd => Renters.Where(x => x.PersonID == cmd.Parameters["@personid_1"].GetValue<int>()).Sum(x => x.Rent));
39+
Context.Database.Instance.AddCommandBehavior(renter_avg, cmd => Renters.Where(x => x.PersonID == cmd.Parameters["@personid_1"].GetValue<int>()).Average(x => x.Rent));
40+
}
41+
42+
1743
[Test]
1844
public void TheCountMethodIsSupported()
1945
{
@@ -25,5 +51,33 @@ public void TheLongCountMethodIsSupported()
2551
{
2652
Context.People.LongCount().Should().BeGreaterThan(0).And.IsOfType<long>();
2753
}
54+
55+
[Test]
56+
public void TheMinMethodIsSupported()
57+
{
58+
Context.People.Min(x => x.ID).Should().Be(1);
59+
}
60+
61+
[Test]
62+
public void TheMaxMethodIsSupported()
63+
{
64+
Context.People.Max(x => x.ID).Should().Be(People.Count);
65+
}
66+
67+
[Test]
68+
public void TheSumMethodIsSupported()
69+
{
70+
Person person = Context.People.Single(x => x.ID == 1);
71+
72+
person.Renters.Sum(x => x.Rent).Should().Be(Renters.Where(x => x.PersonID == person.ID).Sum(x => x.Rent));
73+
}
74+
75+
[Test]
76+
public void TheAverageMethodIsSupported()
77+
{
78+
Person person = Context.People.Single(x => x.ID == 1);
79+
80+
person.Renters.Average(x => x.Rent).Should().Be(Renters.Where(x => x.PersonID == person.ID).Average(x => x.Rent));
81+
}
2882
}
2983
}

SubSonic.Tests/DAL/SUT/BaseTestFixture.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,11 +76,11 @@ public virtual void SetupTestFixture()
7676

7777
Renters = new List<Renter>()
7878
{
79-
new Renter() { PersonID = 1, UnitID = 1, StartDate = new DateTime(1980, 01, 01), EndDate = new DateTime(1990, 02, 28) },
80-
new Renter() { PersonID = 2, UnitID = 1, StartDate = new DateTime(1990, 03, 01) },
81-
new Renter() { PersonID = 3, UnitID = 2, StartDate = new DateTime(1980, 03, 01), EndDate = new DateTime(2000, 01, 01) },
82-
new Renter() { PersonID = 1, UnitID = 3, StartDate = new DateTime(1990, 03, 01) },
83-
new Renter() { PersonID = 4, UnitID = 4, StartDate = new DateTime(2000, 01, 01) }
79+
new Renter() { PersonID = 1, UnitID = 1, Rent = 100M, StartDate = new DateTime(1980, 01, 01), EndDate = new DateTime(1990, 02, 28) },
80+
new Renter() { PersonID = 2, UnitID = 1, Rent = 150M, StartDate = new DateTime(1990, 03, 01) },
81+
new Renter() { PersonID = 3, UnitID = 2, Rent = 200M, StartDate = new DateTime(1980, 03, 01), EndDate = new DateTime(2000, 01, 01) },
82+
new Renter() { PersonID = 1, UnitID = 3, Rent = 250M, StartDate = new DateTime(1990, 03, 01) },
83+
new Renter() { PersonID = 4, UnitID = 4, Rent = 300M, StartDate = new DateTime(2000, 01, 01) }
8484
};
8585

8686
RealEstateProperties = new List<RealEstateProperty>()
@@ -117,14 +117,19 @@ FROM [dbo].[Person] AS [T1]
117117
WHERE ([T1].[ID] > @id_1)",
118118
people_less_than = @"SELECT [T1].[ID], [T1].[FirstName], [T1].[MiddleInitial], [T1].[FamilyName], [T1].[FullName]
119119
FROM [dbo].[Person] AS [T1]
120-
WHERE ([T1].[ID] < @id_1)";
120+
WHERE ([T1].[ID] < @id_1)",
121+
renter_byperson = @"SELECT [T1].[PersonID], [T1].[UnitID], [T1].[Rent], [T1].[StartDate], [T1].[EndDate]
122+
FROM [dbo].[Renter] AS [T1]
123+
WHERE ([T1].[PersonID] == @personid_1)";
121124

122125
Context.Database.Instance.AddCommandBehavior(people_all, cmd => People.ToDataTable());
123126
Context.Database.Instance.AddCommandBehavior(people_all_count, cmd => People.Count());
124127
Context.Database.Instance.AddCommandBehavior(people_all_long_count, cmd => People.LongCount());
125128
Context.Database.Instance.AddCommandBehavior(people_greater_than, cmd => People.Where(x => x.ID > cmd.Parameters["@id_1"].GetValue<int>()).ToDataTable());
126129
Context.Database.Instance.AddCommandBehavior(people_equal, cmd => People.Where(x => x.ID == cmd.Parameters["@id_1"].GetValue<int>()).ToDataTable());
127130
Context.Database.Instance.AddCommandBehavior(people_less_than, cmd => People.Where(x => x.ID < cmd.Parameters["@id_1"].GetValue<int>()).ToDataTable());
131+
132+
Context.Database.Instance.AddCommandBehavior(renter_byperson, cmd => Renters.Where(x => x.PersonID == cmd.Parameters["@personid_1"].GetValue<int>()).ToDataTable());
128133
}
129134

130135
protected virtual void SetInsertBehaviors()

SubSonic/Infrastructure/Builders/DbSqlQueryBuilder/DbSqlQueryBuilderQueryProvider.cs

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,15 @@ public TResult ExecuteMethod<TResult>(MethodCallExpression call)
5353
{
5454
if (unary.Operand is LambdaExpression lambda)
5555
{
56-
where = BuildWhere(dbSelect, lambda);
56+
switch (lambda.Body.NodeType)
57+
{
58+
case ExpressionType.MemberAccess:
59+
dbSelect = (DbSelectExpression)BuildSelect(dbSelect, dbSelect.Columns.Where(x => x.PropertyName.Equals(lambda.GetProperty().Name, StringComparison.Ordinal)));
60+
break;
61+
default:
62+
where = BuildWhere(dbSelect, lambda);
63+
break;
64+
}
5765
}
5866
}
5967
}
@@ -83,7 +91,7 @@ public TResult ExecuteMethod<TResult>(MethodCallExpression call)
8391
throw Error.InvalidOperation($"Method {call.Method.Name} expects data.");
8492
}
8593
}
86-
else if (call.Method.Name.In(nameof(Queryable.Count), nameof(Queryable.LongCount)))
94+
else if (call.Method.Name.In(nameof(Queryable.Count), nameof(Queryable.LongCount), nameof(Queryable.Min), nameof(Queryable.Max), nameof(Queryable.Sum), nameof(Queryable.Average)))
8795
{
8896
if (BuildSelect(dbSelect, where) is DbSelectExpression select)
8997
{
@@ -92,9 +100,20 @@ public TResult ExecuteMethod<TResult>(MethodCallExpression call)
92100
throw Error.NotSupported(SubSonicErrorMessages.MethodNotSupported.Format(call.Method.Name));
93101
}
94102

103+
Expression argument = null;
104+
105+
if (select.Columns.Count > 1)
106+
{
107+
argument = select.Columns.First(x => x.Property.IsPrimaryKey).Expression;
108+
}
109+
else
110+
{
111+
argument = select.Columns.Single().Expression;
112+
}
113+
95114
TResult result = Execute<TResult>(DbExpression.DbSelectAggregate(select, new[]
96115
{
97-
DbExpression.DbAggregate(typeof(TResult), aggregateType, select.Columns.First(x => x.Property.IsPrimaryKey).Expression)
116+
DbExpression.DbAggregate(typeof(TResult), aggregateType, argument)
98117
}));
99118

100119
if (select.Take is ConstantExpression take)

0 commit comments

Comments
 (0)