Created
December 17, 2021 10:43
-
-
Save mickdelaney/be81225cf499375f9e77930fbb1559cf to your computer and use it in GitHub Desktop.
Hotchocolate DDD Style Value Types and Filtering
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| DDD Style Value Types and Filtering | |
| Hi Guys, | |
| I’m trying to migrate a scalar field from String to an EmailAddress class | |
| The EmailAddress class has a String Property called ‘Value’. | |
| As part of the GraphQL Schema there should be a way to filter the User by EmailAddress. | |
| ```csharp | |
| public class EmailAddress | |
| { | |
| public string Value { get; } | |
| public EmailAddress() { } | |
| public EmailAddress(string value) | |
| { | |
| if (value == null) | |
| { | |
| return; | |
| } | |
| Value = value.ToLowerInvariant(); | |
| } | |
| public EmailAddress New(string value) => new EmailAddress(value); | |
| public static readonly ValueConverter<EmailAddress, string> Converter = new | |
| ( | |
| v => v.Value, | |
| v => new EmailAddress(v) | |
| ); | |
| } | |
| ``` | |
| filter type | |
| ```graphql | |
| export type PersonFilter = { | |
| and?: Array<PersonFilter> | null | undefined; | |
| or?: Array<PersonFilter> | null | undefined; | |
| email?: StringOperationFilterInput | null | undefined; | |
| }; | |
| ``` | |
| query | |
| ```graphql | |
| { email: { startsWith: filter } }, | |
| ``` | |
| **Config** | |
| ```csharp | |
| .BindRuntimeType<EmailAddress, StringType>() | |
| .AddTypeConverter<string, EmailAddress>(x => new EmailAddress(x)) | |
| .AddTypeConverter<EmailAddress, string>(x => x.Value); | |
| ``` | |
| *Translates to Linq Query:* | |
| ```sql | |
| where c.Email**.Value** != null | |
| ``` | |
| This fails as that’s not valid SQL. | |
| **Config** | |
| ```csharp | |
| .BindRuntimeType<EmailAddress, EmailAddressType>() | |
| .AddTypeConverter<string, EmailAddress>(x => new EmailAddress(x)) | |
| .AddTypeConverter<EmailAddress, string>(x => x.Value); | |
| ``` | |
| Fails at runtime | |
| Message:Unexpected Execution Error | |
| System.ArgumentException: Method 'Boolean StartsWith(System.String)' declared on type 'System.String' cannot be called with instance of type 'EmailAddress' | |
| at System.Linq.Expressions.Expression.ValidateCallInstanceType(Type instanceType, MethodInfo method) | |
| at System.Linq.Expressions.Expression.ValidateMethodAndGetParameters(Expression instance, MethodInfo method) | |
| at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression arg0) | |
| at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments) at HotChocolate.Data.Filters.Expressions.FilterExpressionBuilder.StartsWith(Expression property, Object value) at HotChocolate.Data.Filters.Expressions.QueryableStringStartsWithHandler.HandleOperation(QueryableFilterContext context, IFilterOperationField field, IValueNode value, Object parsedValue) at HotChocolate.Data.Filters.Expressions.QueryableOperationHandlerBase.TryHandleOperation(QueryableFilterContext context, IFilterOperationField field, ObjectFieldNode node, Expression& result) at HotChocolate.Data.Filters.FilterOperationHandler`2.TryHandleEnter(TContext context, IFilterField field, ObjectFieldNode node, ISyntaxVisitorAction& action) | |
| at HotChocolate.Data.Filters.FilterVisitor`2.OnFieldEnter(TContext context, IFilterField field, ObjectFieldNode node) at HotChocolate.Data.Filters.FilterVisitorBase`2.Enter(ObjectFieldNode node, TContext context) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment