Skip to content

Commit a942022

Browse files
authored
Merge pull request #3 from delegateas/filtergroup
feat: Introduce WhereGroupBuilder for advanced filter grouping
2 parents 02bd34b + 4be2711 commit a942022

File tree

11 files changed

+588
-35
lines changed

11 files changed

+588
-35
lines changed

src/QueryBuilder/ExpandBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace DataverseQuery
1+
namespace DataverseQuery.QueryBuilder
22
{
33
public sealed class ExpandBuilder
44
{
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
using System.Linq.Expressions;
2+
using Microsoft.Xrm.Sdk;
3+
using Microsoft.Xrm.Sdk.Query;
4+
5+
namespace DataverseQuery.QueryBuilder.Extensions
6+
{
7+
/// <summary>
8+
/// Extension methods for WhereGroupBuilder to provide common filter patterns.
9+
/// </summary>
10+
public static class WhereGroupBuilderExtensions
11+
{
12+
/// <summary>
13+
/// Adds an equality condition.
14+
/// </summary>
15+
/// <typeparam name="TEntity">The entity type.</typeparam>
16+
/// <typeparam name="TValue">The value type of the property.</typeparam>
17+
/// <param name="builder">The WhereGroupBuilder instance.</param>
18+
/// <param name="fieldSelector">The lambda expression selecting the field.</param>
19+
/// <param name="value">The value to compare against.</param>
20+
/// <returns>This WhereGroupBuilder instance for method chaining.</returns>
21+
/// <exception cref="ArgumentNullException">Thrown when builder or fieldSelector is null.</exception>
22+
public static WhereGroupBuilder<TEntity> WhereEqual<TEntity, TValue>(
23+
this WhereGroupBuilder<TEntity> builder,
24+
Expression<Func<TEntity, TValue>> fieldSelector,
25+
TValue value)
26+
where TEntity : Entity
27+
{
28+
ArgumentNullException.ThrowIfNull(builder);
29+
return builder.Where(fieldSelector, ConditionOperator.Equal, value);
30+
}
31+
32+
/// <summary>
33+
/// Adds a 'like' condition.
34+
/// </summary>
35+
/// <typeparam name="TEntity">The entity type.</typeparam>
36+
/// <param name="builder">The WhereGroupBuilder instance.</param>
37+
/// <param name="fieldSelector">The lambda expression selecting the field.</param>
38+
/// <param name="pattern">The pattern to match (supports % wildcards).</param>
39+
/// <returns>This WhereGroupBuilder instance for method chaining.</returns>
40+
/// <exception cref="ArgumentNullException">Thrown when builder or fieldSelector is null.</exception>
41+
public static WhereGroupBuilder<TEntity> WhereLike<TEntity>(
42+
this WhereGroupBuilder<TEntity> builder,
43+
Expression<Func<TEntity, string>> fieldSelector,
44+
string pattern)
45+
where TEntity : Entity
46+
{
47+
ArgumentNullException.ThrowIfNull(builder);
48+
return builder.Where(fieldSelector, ConditionOperator.Like, pattern);
49+
}
50+
51+
/// <summary>
52+
/// Adds an 'in' condition.
53+
/// </summary>
54+
/// <typeparam name="TEntity">The entity type.</typeparam>
55+
/// <typeparam name="TValue">The value type of the property.</typeparam>
56+
/// <param name="builder">The WhereGroupBuilder instance.</param>
57+
/// <param name="fieldSelector">The lambda expression selecting the field.</param>
58+
/// <param name="values">The values to check against.</param>
59+
/// <returns>This WhereGroupBuilder instance for method chaining.</returns>
60+
/// <exception cref="ArgumentNullException">Thrown when builder or fieldSelector is null.</exception>
61+
public static WhereGroupBuilder<TEntity> WhereIn<TEntity, TValue>(
62+
this WhereGroupBuilder<TEntity> builder,
63+
Expression<Func<TEntity, TValue>> fieldSelector,
64+
params TValue[] values)
65+
where TEntity : Entity
66+
{
67+
ArgumentNullException.ThrowIfNull(builder);
68+
return builder.Where(fieldSelector, ConditionOperator.In, values);
69+
}
70+
71+
/// <summary>
72+
/// Adds a 'not equal' condition.
73+
/// </summary>
74+
/// <typeparam name="TEntity">The entity type.</typeparam>
75+
/// <typeparam name="TValue">The value type of the property.</typeparam>
76+
/// <param name="builder">The WhereGroupBuilder instance.</param>
77+
/// <param name="fieldSelector">The lambda expression selecting the field.</param>
78+
/// <param name="value">The value to compare against.</param>
79+
/// <returns>This WhereGroupBuilder instance for method chaining.</returns>
80+
/// <exception cref="ArgumentNullException">Thrown when builder or fieldSelector is null.</exception>
81+
public static WhereGroupBuilder<TEntity> WhereNotEqual<TEntity, TValue>(
82+
this WhereGroupBuilder<TEntity> builder,
83+
Expression<Func<TEntity, TValue>> fieldSelector,
84+
TValue value)
85+
where TEntity : Entity
86+
{
87+
ArgumentNullException.ThrowIfNull(builder);
88+
return builder.Where(fieldSelector, ConditionOperator.NotEqual, value);
89+
}
90+
91+
/// <summary>
92+
/// Adds a 'greater than' condition.
93+
/// </summary>
94+
/// <typeparam name="TEntity">The entity type.</typeparam>
95+
/// <typeparam name="TValue">The value type of the property.</typeparam>
96+
/// <param name="builder">The WhereGroupBuilder instance.</param>
97+
/// <param name="fieldSelector">The lambda expression selecting the field.</param>
98+
/// <param name="value">The value to compare against.</param>
99+
/// <returns>This WhereGroupBuilder instance for method chaining.</returns>
100+
/// <exception cref="ArgumentNullException">Thrown when builder or fieldSelector is null.</exception>
101+
public static WhereGroupBuilder<TEntity> WhereGreaterThan<TEntity, TValue>(
102+
this WhereGroupBuilder<TEntity> builder,
103+
Expression<Func<TEntity, TValue>> fieldSelector,
104+
TValue value)
105+
where TEntity : Entity
106+
{
107+
ArgumentNullException.ThrowIfNull(builder);
108+
return builder.Where(fieldSelector, ConditionOperator.GreaterThan, value);
109+
}
110+
111+
/// <summary>
112+
/// Adds a 'less than' condition.
113+
/// </summary>
114+
/// <typeparam name="TEntity">The entity type.</typeparam>
115+
/// <typeparam name="TValue">The value type of the property.</typeparam>
116+
/// <param name="builder">The WhereGroupBuilder instance.</param>
117+
/// <param name="fieldSelector">The lambda expression selecting the field.</param>
118+
/// <param name="value">The value to compare against.</param>
119+
/// <returns>This WhereGroupBuilder instance for method chaining.</returns>
120+
/// <exception cref="ArgumentNullException">Thrown when builder or fieldSelector is null.</exception>
121+
public static WhereGroupBuilder<TEntity> WhereLessThan<TEntity, TValue>(
122+
this WhereGroupBuilder<TEntity> builder,
123+
Expression<Func<TEntity, TValue>> fieldSelector,
124+
TValue value)
125+
where TEntity : Entity
126+
{
127+
ArgumentNullException.ThrowIfNull(builder);
128+
return builder.Where(fieldSelector, ConditionOperator.LessThan, value);
129+
}
130+
131+
/// <summary>
132+
/// Adds a 'null' condition.
133+
/// </summary>
134+
/// <typeparam name="TEntity">The entity type.</typeparam>
135+
/// <typeparam name="TValue">The value type of the property.</typeparam>
136+
/// <param name="builder">The WhereGroupBuilder instance.</param>
137+
/// <param name="fieldSelector">The lambda expression selecting the field.</param>
138+
/// <returns>This WhereGroupBuilder instance for method chaining.</returns>
139+
/// <exception cref="ArgumentNullException">Thrown when builder or fieldSelector is null.</exception>
140+
public static WhereGroupBuilder<TEntity> WhereNull<TEntity, TValue>(
141+
this WhereGroupBuilder<TEntity> builder,
142+
Expression<Func<TEntity, TValue>> fieldSelector)
143+
where TEntity : Entity
144+
{
145+
ArgumentNullException.ThrowIfNull(builder);
146+
return builder.Where(fieldSelector, ConditionOperator.Null);
147+
}
148+
149+
/// <summary>
150+
/// Adds a 'not null' condition.
151+
/// </summary>
152+
/// <typeparam name="TEntity">The entity type.</typeparam>
153+
/// <typeparam name="TValue">The value type of the property.</typeparam>
154+
/// <param name="builder">The WhereGroupBuilder instance.</param>
155+
/// <param name="fieldSelector">The lambda expression selecting the field.</param>
156+
/// <returns>This WhereGroupBuilder instance for method chaining.</returns>
157+
/// <exception cref="ArgumentNullException">Thrown when builder or fieldSelector is null.</exception>
158+
public static WhereGroupBuilder<TEntity> WhereNotNull<TEntity, TValue>(
159+
this WhereGroupBuilder<TEntity> builder,
160+
Expression<Func<TEntity, TValue>> fieldSelector)
161+
where TEntity : Entity
162+
{
163+
ArgumentNullException.ThrowIfNull(builder);
164+
return builder.Where(fieldSelector, ConditionOperator.NotNull);
165+
}
166+
}
167+
}

src/QueryBuilder/IQueryBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using Microsoft.Xrm.Sdk.Query;
22

3-
namespace DataverseQuery
3+
namespace DataverseQuery.QueryBuilder
44
{
55
public interface IQueryBuilder
66
{
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
using System.Linq.Expressions;
2+
using Microsoft.Xrm.Sdk;
3+
4+
namespace DataverseQuery.QueryBuilder.Interfaces
5+
{
6+
/// <summary>
7+
/// Resolves attribute names from lambda expressions.
8+
/// </summary>
9+
public interface IAttributeNameResolver
10+
{
11+
/// <summary>
12+
/// Gets the attribute name from a property selector expression.
13+
/// </summary>
14+
/// <typeparam name="TEntity">The entity type.</typeparam>
15+
/// <typeparam name="TValue">The value type of the property.</typeparam>
16+
/// <param name="fieldSelector">The lambda expression selecting the property.</param>
17+
/// <returns>The attribute name, or null if it cannot be resolved.</returns>
18+
string? GetAttributeName<TEntity, TValue>(Expression<Func<TEntity, TValue>> fieldSelector)
19+
where TEntity : Entity;
20+
}
21+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
namespace DataverseQuery.QueryBuilder.Interfaces
2+
{
3+
/// <summary>
4+
/// Converts values for use in Dataverse queries.
5+
/// </summary>
6+
public interface IValueConverter
7+
{
8+
/// <summary>
9+
/// Converts an array of values to their primitive representations for use in Dataverse queries.
10+
/// </summary>
11+
/// <typeparam name="TValue">The type of values to convert.</typeparam>
12+
/// <param name="values">The values to convert.</param>
13+
/// <returns>An array of converted values suitable for Dataverse queries.</returns>
14+
object[] ConvertValues<TValue>(TValue[] values);
15+
}
16+
}

0 commit comments

Comments
 (0)