-
-
Notifications
You must be signed in to change notification settings - Fork 804
Labels
Area: DataIssue is related to filtering, sorting, pagination or projectionsIssue is related to filtering, sorting, pagination or projections🌶️ hot chocolate
Description
Is there an existing issue for this?
- I have searched the existing issues
Product
Hot Chocolate
Describe the bug
If you use a record in a projection, it will fail because of trying to use the default constructor on it.
Type 'PriceData' does not have a default constructor (Parameter 'type')
Steps to reproduce
- Create a record
- Create a query
- Mark query as projection
- Call the query
- Response has a result with error node
Relevant log output
message
:
"Type 'PriceData' does not have a default constructor (Parameter 'type')"
stackTrace
:
" at System.Linq.Expressions.Expression.New(Type type)\r\n at HotChocolate.Data.Projections.Expressions.QueryableProjectionScopeExtensions.CreateMemberInit(QueryableProjectionScope scope)\r\n at HotChocolate.Data.Projections.Expressions.QueryableProjectionScopeExtensions.CreateMemberInitLambda(QueryableProjection Additional Context?
You can create records with Expressions and turn them in a MemberInitExpression. Still I don't know if this safe and sound.
Below is an attempt to patch CreateMemberInit but this is untested
private static Expression GetMemberInit(Object val)
{
var isRecord = ((TypeInfo) val.Key).DeclaredProperties.Any(x => x.Name == "EqualityContract");
if (isRecord)
{
var ctor = val.Key.GetConstructors()[0];
return Expression.MemberInit(Expression.New(ctor, val.Value.Select(x => x.Expression)));
}
else
{
var ctor = Expression.New(val.Key);
return Expression.MemberInit(ctor, val.Value);
}
}
public static Expression CreateMemberInit(this QueryableProjectionScope scope)
{
if (scope.HasAbstractTypes())
{
Expression lastValue = Expression.Default(scope.RuntimeType);
foreach (var val in scope.GetAbstractTypes())
{
Expression memberInit = GetMemberInit(val);
lastValue = Expression.Condition(
Expression.TypeIs(scope.Instance.Peek(), val.Key),
Expression.Convert(memberInit, scope.RuntimeType),
lastValue);
}
return lastValue;
}
else
{
var ctor = Expression.New(scope.RuntimeType);
return Expression.MemberInit(ctor, scope.Level.Peek());
}
}
Version
13.5.0
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
Area: DataIssue is related to filtering, sorting, pagination or projectionsIssue is related to filtering, sorting, pagination or projections🌶️ hot chocolate