Executing this graphQL Query : < /p>
Код: Выделить всё
query Test {
legalEntity(where: { label: { eq: "TestSociety" } }) {
id
label
}
}
< /code>
дает мне следующую ошибку: < /p>
"extensions": {
"message": "The LINQ expression 'DbSet()\r\n .Where(l => l.Label.Value == __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.QueryCompilationContext.CreateQueryExecutorExpression[TResult](Expression query)\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__DisplayClass11_0`1.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.ExecuteCore[TResult](Expression query, Boolean async, CancellationToken cancellationToken)\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 HotChocolate.DefaultAsyncEnumerableExecutable`1.ToListAsync(CancellationToken cancellationToken)\r\n at HotChocolate.Execution.ListPostProcessor`1.ToCompletionResultAsync(Object result, CancellationToken cancellationToken)\r\n at HotChocolate.Execution.Processing.Tasks.ResolverTask.ExecuteResolverPipelineAsync(CancellationToken cancellationToken)\r\n at HotChocolate.Execution.Processing.Tasks.ResolverTask.TryExecuteAsync(CancellationToken cancellationToken)"
}
Чтобы получить этот результат, я использую hotchocolate
Код: Выделить всё
//Query
[Authorize]
[QueryType]
public class LegalEntityQueries
{
[UseFiltering]
[UseSorting]
public IQueryable GetLegalEntities(
AppDbContext dbContext,
int? limit = null,
int? offset = null
)
{
return dbContext.LegalEntities.TakeIf(limit).SkipIf(offset).ProjectToType();
}
}
< /code>
Чтобы избежать всей моей сущности, у меня есть GQL DTO с равными именами < /p>
//DTO
public record LegalEntityGql
{
public Guid Id { get; init; }
public string Label { get; init; } // As you can see, Label is here as a primitive string
}
< /code>
Чтобы преобразовать мою сущность в GQL, я использую Mapster v7.4.0 < /p>
//Mapster Config
internal sealed class ValueObjectMapsterConfig : IRegister
{
public void Register(TypeAdapterConfig config)
{
config.NewConfig().MapWith(l => l.Value);
}
}
< /code>
mapster и горячий шоколад настроены в моей программе.//Hot Chocolate config
public static class DependencyInjection
{
public static IServiceCollection AddGraphQL(this IServiceCollection services)
{
TypeAdapterConfig.GlobalSettings.Scan(typeof(ValueObjectMapsterConfig).Assembly);
services
.AddGraphQLServer()
.AddAuthorization()
.AddGraphQLTypes()
.AddProjections()
.AddFiltering()
.AddSorting();
MapsterConfiguration.RegisterMappings();
return services;
}
}
< /code>
Я следую над перспективой DDD, с доменом, включая агрегированные корни и объекты значения: < /p>
//Domain object
public class LegalEntity : BaseEntity
{
// 1. Properties
public Label Label { get; private set; }
// 2. Private constructor (used by factories)
private LegalEntity(Guid? id, Label labelt)
: base(id)
{
Label = label;
}
// 3. Factory methods
public static Result Create(Label label) =>
CreateFull(null, label);
public static Result CreateFull(
Guid? id,
Label label,
)
{
//To be reused immediatly, each legalEntity should be created using a new Guid
Guid legalEntityId = id ?? Guid.NewGuid();
return new LegalEntity(legalEntityId, label);
}
// 4. Muleability methods (behavior/modification)
public void UpdateLabel(Label label)
{
Label = label;
}
// ORM constructor
private LegalEntity() { }
}
< /code>
Свойство моей метки предназначено как значение valueObject, чтобы сохранить неизменность внутри домена: < /p>
//ValueObject "Label"
public sealed class Label : ValueObject
{
public const int MaxLength = 50;
public string Value { get; }
private Label(string value)
{
Value = value;
}
public static Result Create(string value)
{
if (string.IsNullOrWhiteSpace(value))
{
return Result.Failure(DomainErrors.Label.Empty);
}
return new Label(value);
}
protected override IEnumerable GetAtomicValues()
{
yield return Value;
}
// ORM constructor
private Label() { }
}
< /code>
Тем не менее, EF сохраняет его как одну строку в SQL и конвертируйте его при чтении из DB: < /p>
public static class AdminModelBuilderExtension
{
public static void ConfigureAdminModule(this ModelBuilder modelBuilder)
{
modelBuilder.Entity(entity =>
{
entity
.Property(le => le.Label)
.HasConversion(le => le.Value, v => Label.Create(v).Value);
entity.HasIndex(le => le.Label).IsUnique();
});
}
}
Чтобы прочитать этикетку GraphQl поля, нет проблем с использованием Mapster и преобразование label. последовательность.
Я воспроизвел проблему, построив 2 ef Queries: < /p>
LegalEntity? test1 = await dbContext
.LegalEntities.OrderBy(le => le.Label)
.FirstOrDefaultAsync(CancellationToken.None);
LegalEntity? test2 = await dbContext
.LegalEntities.OrderBy(le => le.Label.Value)
.FirstOrDefaultAsync(CancellationToken.None);
< /code>
В этом примере Test1 работает успешно (и это нормально!), Но Test2 издает ту же ошибку: < /p>
выражение Linq 'dbset () \ r \ n .orderby (le =>
label.value)' не было переведено. /> Спасибо! < /p>
Подробнее здесь: https://stackoverflow.com/questions/797 ... alueobject
Мобильная версия