ASP.NET Core中使用GraphQL - 第九章 在GraphQL中處理多對多關系


ASP.NET Core中使用GraphQL


上一章中,我們介紹了如何在GraphQL中處理一對多關系,這一章,我們來介紹一下GraphQL中如何處理多對多關系。

我們繼續延伸上一章的需求,上一章中我們引入了客戶和訂單,但是我們沒有涉及訂單中的物品。在實際需求中,一個訂單可以包含多個物品,一個物品也可以屬於多個訂單,所以訂單和物品之間是一個多對多關系。

為了創建訂單和物品之間的關系,這里我們首先創建一個訂單物品實體。

OrderItem
[Table("OrderItems")]
public class OrderItem
{
	public int Id { get; set; }

    public string Barcode { get; set; }

    [ForeignKey("Barcode")]
	public virtual Item Item { get; set; }

	public int Quantity { get; set; }

	public int OrderId { get; set; }

    [ForeignKey("OrderId")]
	public virtual Order Order { get; set; }
}

創建完成之后,我們還需要修改OrderItem實體, 添加他們與OrderItem之間的關系

Order
public class Order
{
	public int OrderId { get; set; }
	public string Tag { get; set; }
	public DateTime CreatedAt { get; set; }

	public Customer Customer { get; set; }
	public int CustomerId { get; set; }

	public virtual ICollection<OrderItem> OrderItems { get; set; }
}
Item
[Table("Items")]
public class Item
{
    [Key]
    public string Barcode { get; set; }

    public string Title { get; set; }

    public decimal SellingPrice { get; set; }

    public virtual ICollection<OrderItem> OrderItems { get; set; }
}

修改完成之后,我們使用如下命令創建數據庫遷移腳本,並更新數據庫

dotnet ef migrations add AddOrderItemTable
dotnet ef database update

遷移成功之后,我們可以添加一個新的GraphQL節點,使用這個新節點,我們可以向訂單中添加物品。為了實現這個功能,我們首先需要為OrderItem實體添加它在GraphQL中對應的類型OrderItemType

OrderItemType
public class OrderItemType : ObjectGraphType<OrderItem>  
{
    public OrderItemType(IDataStore dateStore)
    {   
        Field(i => i.ItemId);      

        Field<ItemType, Item>().Name("Item").ResolveAsync(ctx =>
        {
            return dateStore.GetItemByIdAsync(ctx.Source.ItemId);
        });         

        Field(i => i.Quantity);

        Field(i => i.OrderId);

        Field<OrderType, Order>().Name("Order").ResolveAsync(ctx =>
        {
            return dateStore.GetOrderByIdAsync(ctx.Source.OrderId);
        });

    }
}

第二步,我們還需要創建一個OrderItemInputType來定義添加OrderItem需要哪些字段。

OrderItemInputType
public class OrderItemInputType : InputObjectGraphType  
{
    public OrderItemInputType()
    {
        Name = "OrderItemInput";
        Field<NonNullGraphType<IntGraphType>>("quantity");
        Field<NonNullGraphType<IntGraphType>>("itemId");
        Field<NonNullGraphType<IntGraphType>>("orderId");
    }
}

第三步,我們需要在InventoryMutation類中針對OrderItem添加新的mutation

InventoryMutation
Field<OrderItemType, OrderItem>()  
    .Name("addOrderItem")
    .Argument<NonNullGraphType<OrderItemInputType>>("orderitem", "orderitem input")
    .ResolveAsync(ctx =>
    {
        var orderItem = ctx.GetArgument<OrderItem>("orderitem");
        return dataStore.AddOrderItemAsync(orderItem);
    });

第四步,我們需要在IDataStore接口中定義幾個新的方法,並在DataStore類中實現他們

IDataStore
Task<OrderItem> AddOrderItemAsync(OrderItem orderItem);

Task<Order> GetOrderByIdAsync(int orderId);

Task<IEnumerable<OrderItem>> GetOrderItemByOrderIdAsync(int orderId);
DataStore
public async Task<OrderItem> AddOrderItemAsync(OrderItem orderItem)
{
	var addedOrderItem = await _context.OrderItems.AddAsync(orderItem);
	await _context.SaveChangesAsync();
	return addedOrderItem.Entity;
}

public async Task<Order> GetOrderByIdAsync(int orderId)
{
    return await _context.Orders.FindAsync(orderId);
}

public async Task<IEnumerable<OrderItem>> GetOrderItemByOrderIdAsync(int orderId)
{
    return await _context.OrderItems
        .Where(o => o.OrderId == orderId)
        .ToListAsync();
}

第五步,我們來修改OrderType類,我們希望查詢訂單的時候,可以返回訂單中的所有物品

public class OrderType : ObjectGraphType<Order>
{
    public OrderType(IDataStore dataStore)
    {
        Field(o => o.Tag);
        Field(o => o.CreatedAt);
        Field<CustomerType, Customer>()
        .Name("Customer")
        .ResolveAsync(ctx =>
        {
            return dataStore.GetCustomerByIdAsync(ctx.Source.CustomerId);
        });

        Field<OrderItemType, OrderItem>()
        .Name("Items")
        .ResolveAsync(ctx =>
        {
            return dataStore.GetOrderItemByOrderIdAsync(ctx.Source.OrderId);
        });
        }
    }
}

最后我們還需要在Startup類中注冊我們剛定義的2個新類型

services.AddScoped<OrderItemType>();  
services.AddScoped<OrderItemInputType>();  

以上就是所有的代碼修改。現在我們啟動項目

首先我們先為之前添加的訂單1, 添加兩個物品

然后我們來調用查詢Order的query, 結果中訂單中物品正確顯示了。

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM