Skip to content

Commit 14ace1f

Browse files
committed
Fix: Correctly working Queryable extensions
1 parent ab5c74d commit 14ace1f

File tree

4 files changed

+179
-234
lines changed

4 files changed

+179
-234
lines changed

src/CodeOfChaos.Extensions.EntityFrameworkCore/LinqExtensions.cs

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,17 +10,12 @@ namespace Microsoft.EntityFrameworkCore;
1010
// ---------------------------------------------------------------------------------------------------------------------
1111
public static class LinqExtensions {
1212

13-
public static IQueryable<T> ConditionalInclude<T>(this IQueryable<T> source, bool condition, Expression<Func<T, object>> include) where T : class
14-
=> condition
15-
? source.Include(include)
16-
: source;
17-
1813
public static IQueryable<T> ConditionalWhere<T>(this IQueryable<T> source, bool condition, Expression<Func<T, bool>> predicate)
1914
=> condition
2015
? source.Where(predicate)
2116
: source;
2217

23-
public static IQueryable<T> ConditionalTake<T>(this IQueryable<T> source, bool condition, int count)
18+
public static IQueryable<T> ConditionalTake<T>(this IQueryable<T> source, bool condition, int count)
2419
=> condition
2520
? source.Take(count)
2621
: source;
@@ -30,6 +25,11 @@ public static IQueryable<T> ConditionalTake<T>(this IQueryable<T> source, bool c
3025
? source.Take(range)
3126
: source;
3227

28+
public static IQueryable<T> ConditionalSkip<T>(this IQueryable<T> source, bool condition, int count)
29+
=> condition && count > 0
30+
? source.Skip(count)
31+
: source;
32+
3333
public static IQueryable<T> ConditionalOrderBy<T>(this IQueryable<T> source, bool condition, Expression<Func<T, object>> orderBy)
3434
=> condition
3535
? source.OrderBy(orderBy)
@@ -39,12 +39,41 @@ public static IQueryable<TSource> ConditionalOrderBy<TSource, TKey>(this IQuerya
3939
=> condition
4040
? source.OrderBy(orderBy, comparer)
4141
: source;
42-
43-
public static IQueryable<TSource> ConditionalOrderByNotNull<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>>? orderBy)
42+
43+
public static IQueryable<TSource> ConditionalOrderByNotNull<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>>? orderBy)
4444
=> orderBy is not null
4545
? source.OrderBy(orderBy)
4646
: source;
4747

48+
public static IQueryable<TSource> ConditionalOrderByNotNull<TSource, TKey>(this IQueryable<TSource> source, Expression<Func<TSource, TKey>>? orderBy, IComparer<TKey>? comparer)
49+
=> orderBy is not null
50+
? source.OrderBy(orderBy, comparer)
51+
: source;
52+
53+
public static IQueryable<TSource> ConditionalQuery<TSource>(this IQueryable<TSource> source, bool condition, Func<IQueryable<TSource>, IQueryable<TSource>> queryableFunc)
54+
=> condition
55+
? queryableFunc(source)
56+
: source;
57+
58+
public static IQueryable<T> ConditionalDistinct<T>(this IQueryable<T> source, bool condition)
59+
=> condition
60+
? source.Distinct()
61+
: source;
62+
63+
public static IQueryable<T> ConditionalUnion<T>(this IQueryable<T> source, bool condition, IQueryable<T> second)
64+
=> condition
65+
? source.Union(second)
66+
: source;
67+
68+
public static IQueryable<T> ConditionalIntersect<T>(this IQueryable<T> source, bool condition, IQueryable<T> second)
69+
=> condition
70+
? source.Intersect(second)
71+
: source;
72+
73+
public static IQueryable<T> ConditionalExcept<T>(this IQueryable<T> source, bool condition, IQueryable<T> second)
74+
=> condition
75+
? source.Except(second)
76+
: source;
4877

4978
public static IQueryable<T> ConditionalQueryable<T>(this IQueryable<T> source, bool condition, Func<IQueryable<T>, IQueryable<T>> queryableFunc)
5079
=> condition
@@ -55,4 +84,9 @@ public static IQueryable<T> ConditionalReverse<T>(this IQueryable<T> source, boo
5584
=> reverse
5685
? source.Reverse()
5786
: source;
87+
88+
public static IQueryable<T> ConditionalInclude<T>(this IQueryable<T> source, bool condition, Expression<Func<T, object>> include) where T : class
89+
=> condition
90+
? source.Include(include)
91+
: source;
5892
}

src/CodeOfChaos.Extensions/LinqExtensions.cs

Lines changed: 0 additions & 77 deletions
This file was deleted.

tests/Tests.CodeOfChaos.Extensions.EntityFrameworkCore/LinqExtensionTests.cs

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ namespace Tests.CodeOfChaos.Extensions.EntityFrameworkCore;
1111
// ---------------------------------------------------------------------------------------------------------------------
1212
[TestSubject(typeof(LinqExtensions))]
1313
public class LinqExtensionsTest {
14+
private readonly List<int> _data = Enumerable.Range(1, 10).ToList();// Data: {1, 2, 3, ... 10}
1415

1516
[Test]
1617
[Arguments(true, new[] { "a", "b", "c" }, new[] { "a", "b", "c" })]
@@ -115,4 +116,140 @@ public async Task ConditionalOrderByNotNull_WithKeySelector_ShouldSortCorrectly(
115116
// Assert
116117
await Assert.That(output).IsEquivalentTo(expected);
117118
}
119+
120+
[Test]
121+
public async Task ConditionalWhere_ConditionTrue_ShouldFilter() {
122+
IQueryable<int> source = _data.AsQueryable();
123+
List<int> result = source.ConditionalWhere(true, predicate: x => x > 5).ToList();
124+
125+
await Assert.That(result).IsEquivalentTo([
126+
6, 7, 8, 9, 10
127+
]);
128+
}
129+
130+
[Test]
131+
public async Task ConditionalWhere_ConditionFalse_ShouldNotFilter() {
132+
IQueryable<int> source = _data.AsQueryable();
133+
List<int> result = source.ConditionalWhere(false, predicate: x => x > 5).ToList();
134+
135+
await Assert.That(result).IsEquivalentTo(_data);
136+
}
137+
138+
[Test]
139+
public async Task ConditionalTake_ConditionTrue_ShouldTakeElements() {
140+
IQueryable<int> source = _data.AsQueryable();
141+
List<int> result = source.ConditionalTake(true, 5).ToList();
142+
143+
await Assert.That(result).IsEquivalentTo([
144+
1, 2, 3, 4, 5
145+
]);
146+
}
147+
148+
[Test]
149+
public async Task ConditionalTake_ConditionFalse_ShouldNotTakeElements() {
150+
IQueryable<int> source = _data.AsQueryable();
151+
List<int> result = source.ConditionalTake(false, 5).ToList();
152+
153+
await Assert.That(result).IsEquivalentTo(_data);
154+
}
155+
156+
[Test]
157+
public async Task ConditionalOrderBy_ConditionTrue_ShouldOrder() {
158+
IQueryable<int> source = _data.AsQueryable();
159+
List<int> result = source.ConditionalOrderBy(true, orderBy: x => -x).ToList();
160+
161+
await Assert.That(result).IsEquivalentTo([
162+
10, 9, 8, 7, 6, 5, 4, 3, 2, 1
163+
]);
164+
}
165+
166+
[Test]
167+
public async Task ConditionalOrderBy_ConditionFalse_ShouldNotOrder() {
168+
IQueryable<int> source = _data.AsQueryable();
169+
List<int> result = source.ConditionalOrderBy(false, orderBy: x => -x).ToList();
170+
171+
await Assert.That(result).IsEquivalentTo(_data);
172+
}
173+
174+
[Test]
175+
public async Task ConditionalSkip_ConditionTrue_ShouldSkipElements() {
176+
IQueryable<int> source = _data.AsQueryable();
177+
List<int> result = source.ConditionalSkip(true, 5).ToList();
178+
179+
await Assert.That(result).IsEquivalentTo([
180+
6, 7, 8, 9, 10
181+
]);
182+
}
183+
184+
[Test]
185+
public async Task ConditionalSkip_ConditionFalse_ShouldNotSkipElements() {
186+
IQueryable<int> source = _data.AsQueryable();
187+
List<int> result = source.ConditionalSkip(false, 5).ToList();
188+
189+
await Assert.That(result).IsEquivalentTo(_data);
190+
}
191+
192+
[Test]
193+
public async Task ConditionalDistinct_ConditionTrue_ShouldReturnDistinct() {
194+
IQueryable<int> source = new List<int> { 1, 2, 2, 3, 3, 3 }.AsQueryable();
195+
List<int> result = source.ConditionalDistinct(true).ToList();
196+
197+
await Assert.That(result).IsEquivalentTo([
198+
1, 2, 3
199+
]);
200+
}
201+
202+
[Test]
203+
public async Task ConditionalDistinct_ConditionFalse_ShouldReturnOriginal() {
204+
IQueryable<int> source = new List<int> { 1, 2, 2, 3, 3, 3 }.AsQueryable();
205+
List<int> result = source.ConditionalDistinct(false).ToList();
206+
207+
await Assert.That(result).IsEquivalentTo([
208+
1, 2, 2, 3, 3, 3
209+
]);
210+
}
211+
212+
[Test]
213+
public async Task ConditionalUnion_ConditionTrue_ShouldUnion() {
214+
IQueryable<int> source = new List<int> { 1, 2, 3 }.AsQueryable();
215+
IQueryable<int> second = new List<int> { 3, 4, 5 }.AsQueryable();
216+
List<int> result = source.ConditionalUnion(true, second).ToList();
217+
218+
await Assert.That(result).IsEquivalentTo([
219+
1, 2, 3, 4, 5
220+
]);
221+
}
222+
223+
[Test]
224+
public async Task ConditionalUnion_ConditionFalse_ShouldNotUnion() {
225+
IQueryable<int> source = new List<int> { 1, 2, 3 }.AsQueryable();
226+
IQueryable<int> second = new List<int> { 3, 4, 5 }.AsQueryable();
227+
List<int> result = source.ConditionalUnion(false, second).ToList();
228+
229+
await Assert.That(result).IsEquivalentTo([
230+
1, 2, 3
231+
]);
232+
}
233+
234+
[Test]
235+
public async Task ConditionalExcept_ConditionTrue_ShouldApplyExcept() {
236+
IQueryable<int> source = new List<int> { 1, 2, 3, 4 }.AsQueryable();
237+
IQueryable<int> second = new List<int> { 3, 4, 5 }.AsQueryable();
238+
List<int> result = source.ConditionalExcept(true, second).ToList();
239+
240+
await Assert.That(result).IsEquivalentTo([
241+
1, 2
242+
]);
243+
}
244+
245+
[Test]
246+
public async Task ConditionalExcept_ConditionFalse_ShouldNotApplyExcept() {
247+
IQueryable<int> source = new List<int> { 1, 2, 3, 4 }.AsQueryable();
248+
IQueryable<int> second = new List<int> { 3, 4, 5 }.AsQueryable();
249+
List<int> result = source.ConditionalExcept(false, second).ToList();
250+
251+
await Assert.That(result).IsEquivalentTo([
252+
1, 2, 3, 4
253+
]);
254+
}
118255
}

0 commit comments

Comments
 (0)