ASP.NET Core中使用GraphQL - 第五章 字段, 參數, 變量

ASP.NET Core中使用GraphQLhtml


字段

咱們已經很好的理解了GraphQL中的字段。在以前HelloWorldQuery的例子中,咱們添加了2個字段hellohowdy. 它們都是標量字段。正如GraphQL官網文檔中聲明的那樣git

"At its simplest, GraphQL is about asking for specific fields on objects"github

簡單來講,GraphQL就是詢問對象中的一些特定字段數據庫

來源: graphql.orgjson

下面咱們來爲咱們的實例程序添加一些複雜的類型。好比,如今咱們須要編寫一個庫存系統,咱們首先添加一個貨物類Item, 其代碼以下:c#

public class Item  
{
    public string Barcode { get; set; }

    public string Title { get; set; }

    public decimal SellingPrice { get; set; }
}

可是咱們不但願直接針對這個對象建立查詢,由於它不是一個GraphQL對象,它沒有繼承自ObjectGraphType, 爲了建立一個GraphQL查詢,咱們須要建立一個新類ItemType, 它繼承自ObjectGraphType類。api

另外ObjectGraphType類是一個泛型類,因此這裏咱們須要指定它的泛型參數是Item編碼

public class ItemType : ObjectGraphType<Item>  
{
    public ItemType()
    {
        Field(i => i.Barcode);
        Field(i => i.Title);
        Field(i => i.SellingPrice);
    }
}

這裏有2點須要注意。首先咱們不在針對字段進行類型聲明瞭。GraphQL庫將實體類屬性字段類型映射成GraphQL的內置類型。例如這裏Barcode的類型string會被映射成GraphQL的內置類型StringGraphType。其次這裏咱們使用了Lambda表達式設置了實體類屬性和GraphQL字段之間的映射, 這有點相似於數據庫模型和ViewModel之間的轉換的映射。3d

下一步,咱們須要在HelloWorldQuery中註冊ItemTypecode

public HelloWorldQuery()  
{
    ...
    ...

    Field<ItemType>(
        "item",
        resolve: context =>
        {
           return new Item {
                Barcode = "123",
                Title = "Headphone",
                SellingPrice = 12.99M
            };
        }
    ); 
}

這裏咱們暫時設置了一個硬編碼的返回值。因此當查詢item對象的時候,這個硬編碼的返回值會輸出出來。

如今咱們啓動項目,進入GraphiQL界面

首先咱們設置查詢爲

query {
    item{
        barcode
        sellingPrice
    }
}

運行查詢以後,結果是

{
  "data": {
    "item": {
      "barcode": "123",
      "sellingPrice": 12.99
    }
  }
}

而後咱們修改查詢爲

query {
    item{
        barcode
        sellingPrice
        title
    }
}

運行查詢以後,結果是

{
  "data": {
    "item": {
      "barcode": "123",
      "sellingPrice": 12.99,
      "title": "Headphone"
    }
  }
}

這說明咱們的GraphQL查詢已經生效,api根據咱們須要的字段返回了正確的返回值。

參數

這裏咱們可使用參數去除前面的硬編碼。

爲了說明如何使用參數,這裏咱們首先建立一個數據源類DataSource, 其代碼以下

public class DataSource  
{
    public IList<Item> Items
    {
        get;
        set;
    }

    public DataSource()
    {
        Items = new List<Item>(){
            new Item { Barcode= "123", Title="Headphone", SellingPrice=50},
            new Item { Barcode= "456", Title="Keyboard", SellingPrice= 40},
            new Item { Barcode= "789", Title="Monitor", SellingPrice= 100}
        };
    }

    public Item GetItemByBarcode(string barcode)
    {
        return Items.First(i => i.Barcode.Equals(barcode));
    }
}

這裏除了Items集合,咱們還添加了一個方法GetItemByBarcode, 這個方法能夠根據傳遞的barcode參數返回第一個匹配的Item

而後如今咱們來修改以前的item查詢, 添加一個arguments參數, 其代碼以下:

Field<ItemType>(
    "item",
    arguments: new QueryArguments(new QueryArgument<StringGraphType> { Name = "barcode" }),
    resolve: context =>
    {
        var barcode = context.GetArgument<string>("barcode");
        return new DataSource().GetItemByBarcode(barcode);
    }
);

arguments是一個參數列表,裏面能夠包含必填參數和選填參數。針對每一個參數,咱們都須要指定它對應的類型,這裏Name屬性是設置了當前參數的名稱。

resolve參數中, 你可使用context.GetArgument () 方法獲取查詢中傳遞的參數值。

如今咱們從新啓動項目,並在GraphiQL中添加以下查詢

query {  
  item (barcode: "123") {
    title
    sellingPrice
  }
}

輸出的查詢結果

{
  "data": {
    "item": {
      "title": "Headphone",
      "sellingPrice": 50
    }
  }
}

這個結果與咱們預想的同樣。

可是這時候若是咱們不傳遞barcode參數

query {  
  item {
    title
    sellingPrice
  }
}

程序就會報錯

{
  "data": {
    "item": null
  },
  "errors": [
    {
      "message": "Error trying to resolve item.",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "item"
      ],
      "extensions": {
        "code": "INVALID_OPERATION"
      }
    }
  ]
}

緣由是當前barcode是一個可空項,程序查詢時, First方法會報錯。因此這時候咱們可使用NonNullGraphType 來設置barcode爲一個必填項。

QueryArgument<NonNullGraphType<StringGraphType>> { Name = "barcode" }

這樣從新啓動項目後,繼續使用以前報錯的查詢,GraphiQL就會給出校驗錯誤。

變量

如今是時候將參數變成動態了。 咱們不但願每次在查詢中寫死查詢條件,咱們但願這個查詢參數是動態的,這時候咱們就須要使用到變量。

首先,這裏咱們須要確保咱們的GraphQL中間件能夠接受參數,因此咱們須要在GraphQLRequest類中添加一個參數變量

public class GraphQLRequest
{
    public string Query { get; set; }
    public JObject Variables { get; set; }
}

而後咱們須要修改GraphQLMiddleware中間件的InvokeAsync方法, 在其中添加一行代碼設置doc.Inputs

var result = await _executor.ExecuteAsync(doc =>
{
    doc.Schema = _schema;
    doc.Query = request.Query;

    doc.Inputs = request.Variables.ToInputs();

}).ConfigureAwait(false);

如今咱們的item查詢已經支持動態參數了,咱們能夠運行程序,在GraphiQL中設置以下查詢

query($barcode: String!){  
  item(barcode: $barcode){
    title
    sellingPrice
  }
}

查詢中變量是以$開頭的, 後面須要加上變量類型,由於以前咱們這是了barcode參數爲必填項,因此$barcode變量咱們也要設置成必填。變量的必填設置是在變量類型後添加一個!號。

最後,在GraphiQL中,你可使用QUERY VARIABLES面板中輸入參數的值。以下圖所示,最終結果正確的返回了。

本文源代碼:https://github.com/lamondlu/GraphQL_Blogs/tree/master/Part%20V

相關文章
相關標籤/搜索