Open CasperCBroeren opened 1 year ago
+1 on this. A work around i've used is creating a default constructor on your record, eg:
// In Query File.
[UseSingleOrDefault]
[UseProjection]
public IQueryable<Api.User?> GetUserById([Service] DbContext db, Guid userId)
{
// Note: Db model is different to API model, need to only select out the fields that are required for GraphQL
return db.Users.AsNoTracking().Where(x => x.Id == userId).Select(x => new Api.User(x.Id, x.Title, x.FirstName));
}
// ...
// API model
public record User(
Guid Id,
string Title,
string FirstName
)
{
// Workaround default constructor issue
public User() : this(Guid.NewGuid(), "", "")
{
}
}
However that opens up the record to being used incorrectly (accidentally using the default constructor) in other parts of code, which isn't ideal. I'm also unsure if this will cause other issues.
I'm using Hot Chocolate 13.5.1.
Any further updates on this bug?
I have created a default constructor on my record
public record Organisation(
Guid Key,
string? DisplayName,
string? LegalName,
string? TradingName,
DateTime CreatedOn,
bool IsActive,
List<BusinessUnit> BusinessUnits,
Partner? Partner,
Address? Address,
Guid ContractNumber)
{
public Organisation() : this(new Guid(), string.Empty, string.Empty, string.Empty, DateTime.MinValue,
false, new List<BusinessUnit>(), null, null, new Guid())
{
}
}
But now I get a LINQ issue where all my mapping has been working perfectly until I tried to add UseProjection
and UseFiltering
.
{
"errors": [
{
"message": "Unexpected Execution Error",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"organisations"
],
"extensions": {
"message": "The LINQ expression 'DbSet<Organisation>()\r\n .Join(\r\n inner: DbSet<Partner>(), \r\n outerKeySelector: o => EF.Property<int?>(o, \"PartnerId\"), \r\n innerKeySelector: p => EF.Property<int?>(p, \"Id\"), \r\n resultSelector: (o, i) => new TransparentIdentifier<Organisation, Partner>(\r\n Outer = o, \r\n Inner = i\r\n ))\r\n .LeftJoin(\r\n inner: DbSet<Address>(), \r\n outerKeySelector: o => EF.Property<int?>(o.Outer, \"AddressId\"), \r\n innerKeySelector: a => EF.Property<int?>(a, \"Id\"), \r\n resultSelector: (o, i) => new TransparentIdentifier<TransparentIdentifier<Organisation, Partner>, Address>(\r\n Outer = o, \r\n Inner = i\r\n ))\r\n .Where(o => new Organisation{ }\r\n .ContractNumber == __p_0)' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.",
"stackTrace": " at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.Translate(Expression expression)\r\n at Microsoft.EntityFrameworkCore.Query.RelationalQueryableMethodTranslatingExpressionVisitor.Translate(Expression expression)\r\n at Microsoft.EntityFrameworkCore.Query.QueryCompilationContext.CreateQueryExecutor[TResult](Expression query)\r\n at Microsoft.EntityFrameworkCore.Storage.Database.CompileQuery[TResult](Expression query, Boolean async)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.CompileQueryCore[TResult](IDatabase database, Expression query, IModel model, Boolean async)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass12_0`1.<ExecuteAsync>b__0()\r\n at Microsoft.EntityFrameworkCore.Query.Internal.CompiledQueryCache.GetOrAddQuery[TResult](Object cacheKey, Func`1 compiler)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.ExecuteAsync[TResult](Expression query, CancellationToken cancellationToken)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.ExecuteAsync[TResult](Expression expression, CancellationToken cancellationToken)\r\n at Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1.GetAsyncEnumerator(CancellationToken cancellationToken)\r\n at System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable`1.GetAsyncEnumerator()\r\n at Microsoft.EntityFrameworkCore.EntityFrameworkQueryableExtensions.ToListAsync[TSource](IQueryable`1 source, CancellationToken cancellationToken)\r\n at HotChocolate.Data.ToListMiddleware`1.InvokeAsync(IMiddlewareContext context)\r\n at HotChocolate.Types.EntityFrameworkObjectFieldDescriptorExtensions.<>c__DisplayClass3_1`1.<<UseDbContext>b__3>d.MoveNext()\r\n--- End of stack trace from previous location ---\r\n at HotChocolate.Execution.Processing.Tasks.ResolverTask.ExecuteResolverPipelineAsync(CancellationToken cancellationToken)\r\n at HotChocolate.Execution.Processing.Tasks.ResolverTask.TryExecuteAsync(CancellationToken cancellationToken)"
}
}
],
"data": null
}
Is this a version issue between AutoMapper and Hot Chocolate?
Is there an existing issue for this?
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
Relevant log output
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
Version
13.5.0