ASP.NET Core中使用GraphQL - 第九章 在GraphQL中处理多对多关系

ASP.NET Core中使用GraphQLhtml


上一章中,咱们介绍了如何在GraphQL中处理一对多关系,这一章,咱们来介绍一下GraphQL中如何处理多对多关系。git

咱们继续延伸上一章的需求,上一章中咱们引入了客户和订单,可是咱们没有涉及订单中的物品。在实际需求中,一个订单能够包含多个物品,一个物品也能够属于多个订单,因此订单和物品之间是一个多对多关系。github

为了建立订单和物品之间的关系,这里咱们首先建立一个订单物品实体。数据库

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之间的关系c#

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; }
}

修改完成以后,咱们使用以下命令建立数据库迁移脚本,并更新数据库async

dotnet ef migrations add AddOrderItemTable
dotnet ef database update

迁移成功以后,咱们能够添加一个新的GraphQL节点,使用这个新节点,咱们能够向订单中添加物品。为了实现这个功能,咱们首先须要为OrderItem实体添加它在GraphQL中对应的类型OrderItemTypecode

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须要哪些字段。htm

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类中实现他们blog

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

相关文章
相关标签/搜索