• ASP.NET Core中使用GraphQL


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

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

    为了创建订单和物品之间的关系,这里我们首先创建一个订单物品实体。

    OrderItem
    Copy
    [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
    Copy
    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
    Copy
    [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; }
    }

    修改完成之后,我们使用如下命令创建数据库迁移脚本,并更新数据库

    Copy
    dotnet ef migrations add AddOrderItemTable
    dotnet ef database update

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

    OrderItemType
    Copy
    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
    Copy
    public class OrderItemInputType : InputObjectGraphType  
    {
        public OrderItemInputType()
        {
            Name = "OrderItemInput";
            Field<NonNullGraphType<IntGraphType>>("quantity");
            Field<NonNullGraphType<IntGraphType>>("itemId");
            Field<NonNullGraphType<IntGraphType>>("orderId");
        }
    }

    第三步,我们需要在InventoryMutation类中针对OrderItem添加新的mutation

    InventoryMutation
    Copy
    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
    Copy
    Task<OrderItem> AddOrderItemAsync(OrderItem orderItem);
    
    Task<Order> GetOrderByIdAsync(int orderId);
    
    Task<IEnumerable<OrderItem>> GetOrderItemByOrderIdAsync(int orderId);
    DataStore
    Copy
    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类,我们希望查询订单的时候,可以返回订单中的所有物品

    Copy
    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个新类型

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

    以上就是所有的代码修改。现在我们启动项目

    首先我们先为之前添加的订单1, 添加两个物品

    然后我们来调用查询Order的query, 结果中订单中物品正确显示了。

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

  • 相关阅读:
    821. 字符的最短距离
    1122. 数组的相对排序
    258. 各位相加
    C++常见问题之二#define使用中的陷阱
    python进阶二_基本数据类型与操作
    DirectX10一变换(三)
    Android中编译工具链的改动----LLVM份量的增加
    DirectX10一矩阵代数(二)
    DirectX10一向量代数(一)
    基于asp.net + easyui框架,一步步学习easyui-datagrid——实现添加、编辑、删除(三)
  • 原文地址:https://www.cnblogs.com/lhxsoft/p/11903571.html
Copyright © 2020-2023  润新知