首页 > 解决方案 > c#中使用graphql的嵌套查询

问题描述

我试图在 C# 中实现一个 graphql api。我有基本的工作,但我正在努力让嵌套查询工作。

我已经看到它在 NodeJS 和其他人中实现。我只是想知道是否有人可以帮助我在 c# 中实现相同的功能。

基本类型:

 public AirportType()
    {
        Name = "Airport";

        Field(x => x.Id, type: typeof(IdGraphType)).Description("The ID of the Airport.");
        Field(x => x.Name).Description("The name of the Airport");
        Field(x => x.Location).Description("The Location of the Airport");
        Field(x => x.Plane,nullable:true, type: typeof(ListGraphType<PlaneType>)).Description("Aiports Planes");

    }


  public PlaneType()
    {
        Name = "Plane";

        Field(x => x.Id, type: typeof(IdGraphType)).Description("The ID of the Plane.");
        Field(x => x.Model).Description("The model of the Plane");
        Field(x => x.Callsign).Description("The callsign of the Plane");
        Field(x => x.AirportId,nullable:true).Description("The parent Aiport");
        Field(x => x.Pilot,nullable:true, type: typeof(ListGraphType<PilotType>)).Description("The Planes Pilots");
    }



 public PilotType()
    {
        Name = "Pilot";

        Field(x => x.Id, type: typeof(IdGraphType)).Description("The ID of the Pilot.");
        Field(x => x.Name).Description("The name of the Pilot");
        Field(x => x.Surname).Description("The surname of the Pilot");
        Field(x => x.PlaneId,nullable: true).Description("The parent Plane");
    }

和基本查询:

 Field<AirportType>(
            "airport",
            arguments: new QueryArguments(
                new QueryArgument<IdGraphType> { Name = "id", Description = "The ID of the aiport." }),
            resolve: context =>
            {
                var id = context.GetArgument<int?>("id");
                var airport = db.Airport.Include("Plane.Pilot").FirstOrDefault(i => i.Id == id);

                return airport;
            });
        Field<ListGraphType<AirportType>>(
            "airports",
            resolve: context =>
            {
                var airports = db.Airport.Include("Plane.Pilot");

                return airports;
            });
        Field<ListGraphType<PlaneType>>(
            "planes",
            resolve: context =>
            {
                var planes = db.Plane.Include("Pilot").Include("Airport");

                return planes;
            });

标签: c#graphql

解决方案


AirportType、PilotType 和 PlaneType 需要扩展 ObjectGraphType<>

public class Airport
{
    public IdGraphType Id { get; set; }
    public string Name { get; set; }
    public string Location { get; set; }
    public PlaneType Plane { get; set; }
}

public class AirportType : ObjectGraphType<Airport>
{
    public AirportType()
    {
        Name = "Airport";

        Field(x => x.Id, type: typeof(IdGraphType)).Description("The ID of the Airport.");
        Field(x => x.Name).Description("The name of the Airport");
        Field(x => x.Location).Description("The Location of the Airport");
        Field(x => x.Plane, nullable: true, type: typeof(ListGraphType<PlaneType>)).Description("Aiports Planes");
    }
}

public class Pilot
{
    public IdGraphType Id { get; set; }
    public string Name { get; set; }
    public string Surname { get; set; }
    public IdGraphType PlaneId { get; set; }
}

public class PilotType : ObjectGraphType<Pilot>
{
    public PilotType()
    {
        Name = "Pilot";

        Field(x => x.Id, type: typeof(IdGraphType)).Description("The ID of the Pilot.");
        Field(x => x.Name).Description("The name of the Pilot");
        Field(x => x.Surname).Description("The surname of the Pilot");
        Field(x => x.PlaneId, nullable: true).Description("The parent Plane");
    }
}

public class Plane
{
    public IdGraphType Id { get; set; }
    public string Model { get; set; }
    public string Callsign { get; set; }
    public string AirportId { get; set; }
    public PilotType Pilot { get; set; }
}

public class PlaneType : ObjectGraphType<Plane>
{
    public PlaneType()
    {
        Name = "Plane";

        Field(x => x.Id, type: typeof(IdGraphType)).Description("The ID of the Plane.");
        Field(x => x.Model).Description("The model of the Plane");
        Field(x => x.Callsign).Description("The callsign of the Plane");
        Field(x => x.AirportId, nullable: true).Description("The parent Aiport");
        Field(x => x.Pilot, nullable: true, type: typeof(ListGraphType<PilotType>)).Description("The Planes Pilots");
    }
}

GraphQL 查询类还必须扩展 ObjectGraphType

public class MyQuery : ObjectGraphType
{
    public MyQuery(IAirForceRepository db)
    {
        Field<AirportType>(
            "airport",
            arguments: new QueryArguments(
                new QueryArgument<IdGraphType> { Name = "id", Description = "The ID of the airport." }),
            resolve: context =>
            {
                var id = context.GetArgument<int?>("id");
                var airport = db.Airport.Include("Plane.Pilot").FirstOrDefault(i => i.Id == id);

                return airport;
            });
        Field<ListGraphType<AirportType>>(
            "airports",
            resolve: context =>
            {
                var airports = db.Airport.Include("Plane.Pilot");

                return airports;
            });
        Field<ListGraphType<PlaneType>>(
            "planes",
            resolve: context =>
            {
                var planes = db.Plane.Include("Pilot").Include("Airport");

                return planes;
            });
    }
}

为了查询子实体(例如 Plane 和 Pilot),您需要在两者之间添加一个 Connection。在这个例子中,在 Plane 和 Pilot 之间,Plane 是根,Pilot 是子实体,这两个类必须修改如下

修改平面类

public class Plane
{
    public IdGraphType Id { get; set; }
    public string Model { get; set; }
    public string Callsign { get; set; }
    public string AirportId { get; set; }
    public PilotType Pilot { get; set; }
    public Connection<Pilot> PilotConnection { get; set; }

    public Plane()
    {
        PilotConnection = new Connection<Pilot>
        {
            TotalCount = 3,

            PageInfo = new PageInfo
            {
                HasNextPage = false,
                HasPreviousPage = false,
                StartCursor = "0",
                EndCursor = "2",
            },

            Edges = new List<Edge<Pilot>>
            {
                new Edge<Pilot> {Cursor = "0", Node = new Pilot { Name = "Johnny", Id = new IdGraphType() }},
                new Edge<Pilot> {Cursor = "1", Node = new Pilot { Name = "Ronny", Id = new IdGraphType() }},
                new Edge<Pilot> {Cursor = "2", Node = new Pilot {Name = "Jimmy", Id = new IdGraphType() }}
            }
        };
    }
}

修改 PlaneType 类

public class PlaneType : ObjectGraphType<Plane>
    {
        public PlaneType()
        {
            Name = "Plane";

            Field(x => x.Id, type: typeof(IdGraphType)).Description("The ID of the Plane.");
            Field(x => x.Model).Description("The model of the Plane");
            Field(x => x.Callsign).Description("The callsign of the Plane");
            Field(x => x.AirportId, nullable: true).Description("The parent Aiport");
            Field(x => x.Pilot, nullable: true, type: typeof(ListGraphType<PilotType>)).Description("The Planes Pilots");
            Connection<PilotType>()
                .Name("pilots")
                .Description("Pilots that drive this plane")
                .Resolve(context => context.Source.PilotConnection);
        }
    }

然后,您可以对与该子实体的连接执行查询,但无需为其提供参数(例如 id:"1"),如下例所示

query {
    plane(id: "1"){
        id
        model
        callsign
        airportid
        pilot {
            edges {
                node {
                id
                name
                }
            }
        }
    }
}

推荐阅读