嵌套对象的 ASP.NET CORE Hot Chocolate 查询错误

Posted

技术标签:

【中文标题】嵌套对象的 ASP.NET CORE Hot Chocolate 查询错误【英文标题】:ASP.NET CORE Hot Chocolate query error for nested object 【发布时间】:2021-12-25 09:02:39 【问题描述】:

我正在学习如何在 asp.net core 5 项目中编写 GraphQL。我正在使用 Hot Chocolate v5,执行以下查询时出错:

query

  platform
  
    id
    name,
    commands
    
      id
      howTo
      commandLine
    
  

执行此查询时出现以下错误: “错误”:[ "message": "在 commands 字段中找不到名称为 platform 的参数。", “地点”:[ “行”:7, “列”:5 ], “小路”: [ “平台”, 4、 “命令” ], “扩展”: "fieldName": "命令", “参数名称”:“平台” , ...

如果我在以下查询中执行查询,那么它的工作原理:

query

  platform
  
    id
    name
  


query

  command
  
    id
    howTo
    commandLine
  

我认为与此错误相关的代码片段是:

public class Command
    
        /// <summary>
        /// Represents the unique ID for the command.
        /// </summary>
        [Key]
        public int Id  get; set; 

        /// <summary>
        /// Represents the how-to for the command.
        /// </summary>
        [Required]
        public string HowTo  get; set; 

        /// <summary>
        /// Represents the command line.
        /// </summary>
        [Required]
        public string CommandLine  get; set; 

        /// <summary>
        /// Represents the unique ID of the platform which the command belongs.
        /// </summary>
        [Required]
        public int PlatformId  get; set; 

        /// <summary>
        /// This is the platform to which the command belongs.
        /// </summary>
        public Platform Platform  get; set; 
    

public class AppDbContext : DbContext
    
        public AppDbContext(DbContextOptions options) : base(options)
        
        

        public DbSet<Platform> Platforms  get; set; 
        public DbSet<Command> Commands  get; set; 

        protected override void OnModelCreating(ModelBuilder builder)
        
            builder.Entity<Platform>()
                   .HasMany(x => x.Commands)
                   .WithOne(x => x.Platform!)
                   .HasForeignKey(x => x.PlatformId);

            builder.Entity<Command>()
                   .HasOne(x => x.Platform)
                   .WithMany(x => x.Commands)
                   .HasForeignKey(x => x.PlatformId);
        
    

[GraphQLDescription("Represents the queries available.")]
    public class Query
    
        /// <summary>
        /// Gets the queryable <see cref="Command"/>.
        /// </summary>
        /// <param name="context">The <see cref="AppDbContext"/>.</param>
        /// <returns>The queryable <see cref="Command"/>.</returns>
        [UseDbContext(typeof(AppDbContext))]
        [UseFiltering]
        [UseSorting]
        [GraphQLDescription("Gets the queryable command.")]
        public IQueryable<Command> GetCommand([ScopedService] AppDbContext context)
        
            return context.Commands;
        

        /// <summary>
        /// Gets the queryable <see cref="Platform"/>.
        /// </summary>
        /// <param name="context">The <see cref="AppDbContext"/>.</param>
        /// <returns>The queryable <see cref="Platform"/>.</returns>
        [UseDbContext(typeof(AppDbContext))]
        [UseFiltering]
        [UseSorting]
        [GraphQLDescription("Gets the queryable platform.")]
        public IQueryable<Platform> GetPlatform([ScopedService] AppDbContext context)
        
            return context.Platforms;
        

public class PlatformType : ObjectType<Platform>
    
        protected override void Configure(IObjectTypeDescriptor<Platform> descriptor)
        
            descriptor.Description("Represents any software or service that has a command line interface.");

            descriptor.Field(p => p.Id)
                      .Description("Represents the unique ID for the platform.");

            descriptor.Field(p => p.Name)
                      .Description("Represents the name for the platform.");

            descriptor.Field(p => p.LicenceKey)
                      .Ignore();

            descriptor.Field(p => p.Commands)
                      .ResolveWith<Resolvers>(p => p.GetCommands(default!, default!))
                      .UseDbContext<AppDbContext>()
                      .Description("This is the list of available commands for this platform.");
        

        private class Resolvers
        
            public IQueryable<Command> GetCommands(Platform platform, [ScopedService] AppDbContext context)
            
                return context.Commands.Where(p => p.PlatformId == platform.Id);
            
        

public class CommandType : ObjectType<Command>
    
        protected override void Configure(IObjectTypeDescriptor<Command> descriptor)
        
            descriptor.Description("Represents any executable command.");

            descriptor.Field(c => c.Id)
                      .Description("Represents the unique ID for the command.");

            descriptor.Field(c => c.HowTo)
                      .Description("Represents the how-to for the command.");

            descriptor.Field(c => c.CommandLine)
                      .Description("Represents the command line.");

            descriptor.Field(c => c.PlatformId)
                      .Description("Represents the unique ID of the platform which the command belongs.");

            descriptor.Field(c => c.Platform)
                      .ResolveWith<Resolvers>(c => c.GetPlatform(default!, default!))
                      .UseDbContext<AppDbContext>()
                      .Description("This is the platform to which the command belongs.");

        

        private class Resolvers
        
            public Platform GetPlatform(Command command, [ScopedService] AppDbContext context)
            
                return context.Platforms.FirstOrDefault(p => p.Id == command.PlatformId);
            
        

public class Startup
    
        private IConfiguration Configuration  get; 

        public Startup(IConfiguration collection)
        
            Configuration = collection;
        

        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        
            services.ConfigureDbContext(Configuration);
            services.ConfigureGraphQL();
        

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        
            if (env.IsDevelopment())
            
                app.UseDeveloperExceptionPage();
            

            app.UseWebSockets();
            app.UseRouting();

            app.UseEndpoints(endpoints =>
            
                endpoints.MapGraphQL();
            );

            app.ConfigureGraphQL();
        

public static class ContexConfiguration
    
        public static void ConfigureDbContext(this IServiceCollection services, IConfiguration configuration)
        
            services.AddPooledDbContextFactory<AppDbContext>(options =>
               options.UseSqlServer(configuration.GetConnectionString("DefaultConnection")));
        
    

public static class GraphQLConfiguration
    
        /// <summary>
        /// Configuration of the GrapQL server
        /// </summary>
        /// <param name="services"></param>
        public static void ConfigureGraphQL(this IServiceCollection services)
        
            services.AddGraphQLServer()
                    .AddQueryType<Query>()
                    .AddMutationType<Mutation>()
                    .AddSubscriptionType<Subscription>()
                    .AddType<PlatformType>()
                    .AddType<AddPlatformInputType>()
                    .AddType<AddPlatformPayloadType>()
                    .AddType<CommandType>()
                    .AddType<AddCommandInputType>()
                    .AddType<AddCommandPayloadType>()
                    .AddFiltering()
                    .AddSorting()
                    .AddInMemorySubscriptions();
        

        /// <summary>
        /// GraphQL Voyager UI configuration
        /// </summary>
        /// <param name="app"></param>
        public static void ConfigureGraphQL(this IApplicationBuilder app)
        
            app.UseGraphQLVoyager(
                options: new VoyagerOptions()
                
                    GraphQLEndPoint = "/graphql"

                ,
                path: "/graphql-voyager"
            );
        
    

【问题讨论】:

【参考方案1】:

找到amswer

官方documentation:

【讨论】:

以上是关于嵌套对象的 ASP.NET CORE Hot Chocolate 查询错误的主要内容,如果未能解决你的问题,请参考以下文章

Asp.Net Core-几行代码解决Razor中的嵌套if语句

ASP.NET Core 应用程序解决方案资源管理器中的文件嵌套

Asp.net core 配置文件

ASP.NET Core DI 手动获取注入对象

ASP.NET Core Web 应用程序系列- 在ASP.NET Core中使用AutoMapper进行实体映射

ASP.NET Core实现对象自动映射-AgileMapper