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; }}
创建完成之后,我们还需要修改Order
和Item
实体, 添加他们与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 ICollectionOrderItems { 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 ICollectionOrderItems { get; set; }}
修改完成之后,我们使用如下命令创建数据库迁移脚本,并更新数据库
dotnet ef migrations add AddOrderItemTabledotnet ef database update
迁移成功之后,我们可以添加一个新的GraphQL
节点,使用这个新节点,我们可以向订单中添加物品。为了实现这个功能,我们首先需要为OrderItem
实体添加它在GraphQL
中对应的类型OrderItemType
OrderItemType
public class OrderItemType : ObjectGraphType{ public OrderItemType(IDataStore dateStore) { Field(i => i.ItemId); Field ().Name("Item").ResolveAsync(ctx => { return dateStore.GetItemByIdAsync(ctx.Source.ItemId); }); Field(i => i.Quantity); Field(i => i.OrderId); Field ().Name("Order").ResolveAsync(ctx => { return dateStore.GetOrderByIdAsync(ctx.Source.OrderId); }); }}
第二步,我们还需要创建一个OrderItemInputType
来定义添加OrderItem
需要哪些字段。
OrderItemInputType
public class OrderItemInputType : InputObjectGraphType { public OrderItemInputType() { Name = "OrderItemInput"; Field>("quantity"); Field >("itemId"); Field >("orderId"); }}
第三步,我们需要在InventoryMutation
类中针对OrderItem
添加新的mutation
。
InventoryMutation
Field() .Name("addOrderItem") .Argument >("orderitem", "orderitem input") .ResolveAsync(ctx => { var orderItem = ctx.GetArgument ("orderitem"); return dataStore.AddOrderItemAsync(orderItem); });
第四步,我们需要在IDataStore
接口中定义几个新的方法,并在DataStore
类中实现他们
IDataStore
TaskAddOrderItemAsync(OrderItem orderItem);Task GetOrderByIdAsync(int orderId);Task > GetOrderItemByOrderIdAsync(int orderId);
DataStore
public async TaskAddOrderItemAsync(OrderItem orderItem){ var addedOrderItem = await _context.OrderItems.AddAsync(orderItem); await _context.SaveChangesAsync(); return addedOrderItem.Entity;}public async Task GetOrderByIdAsync(int orderId){ return await _context.Orders.FindAsync(orderId);}public async Task > GetOrderItemByOrderIdAsync(int orderId){ return await _context.OrderItems .Where(o => o.OrderId == orderId) .ToListAsync();}
第五步,我们来修改OrderType
类,我们希望查询订单的时候,可以返回订单中的所有物品
public class OrderType : ObjectGraphType{ public OrderType(IDataStore dataStore) { Field(o => o.Tag); Field(o => o.CreatedAt); Field () .Name("Customer") .ResolveAsync(ctx => { return dataStore.GetCustomerByIdAsync(ctx.Source.CustomerId); }); Field () .Name("Items") .ResolveAsync(ctx => { return dataStore.GetOrderItemByOrderIdAsync(ctx.Source.OrderId); }); } }}
最后我们还需要在Startup
类中注册我们刚定义的2个新类型
services.AddScoped(); services.AddScoped ();
以上就是所有的代码修改。现在我们启动项目
首先我们先为之前添加的订单1, 添加两个物品
然后我们来调用查询Order的query
, 结果中订单中物品正确显示了。