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

ASP.NET Core中使用GraphQL
- ASP.NET Core中使用GraphQL - 第一章 Hello World
- ASP.NET Core中使用GraphQL - 第二章 中间件
- ASP.NET Core中使用GraphQL - 第三章 依赖注入
- ASP.NET Core中使用GraphQL - 第四章 GrahpiQL
- ASP.NET Core中使用GraphQL - 第五章 字段, 参数, 变量
- ASP.NET Core中使用GraphQL - 第六章 使用EF Core作为持久化仓储
- ASP.NET Core中使用GraphQL - 第七章 Mutation
- ASP.NET Core中使用GraphQL - 第八章 在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 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
ASP.NET Core中使用GraphQL - 第九章 在GraphQL中处理多对多关系的更多相关文章
- 【无私分享:ASP.NET CORE 项目实战(第九章)】创建区域Areas,添加TagHelper
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 在Asp.net Core VS2015中,我们发现还有很多不太简便的地方,比如右击添加视图,转到试图页等功能图不见了,虽然我 ...
- [转]【无私分享:ASP.NET CORE 项目实战(第九章)】创建区域Areas,添加TagHelper
本文转自:http://www.cnblogs.com/zhangxiaolei521/p/5808417.html 目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 在Asp ...
- Pro ASP.Net Core MVC 6th 第四章
第四章 C# 关键特征 在本章中,我描述了Web应用程序开发中使用的C#特征,这些特征尚未被广泛理解或经常引起混淆. 这不是关于C#的书,但是,我仅为每个特征提供一个简单的例子,以便您可以按照本书其余 ...
- 【新书推荐】《ASP.NET Core微服务实战:在云环境中开发、测试和部署跨平台服务》 带你走近微服务开发
<ASP.NET Core 微服务实战>译者序:https://blog.jijiechen.com/post/aspnetcore-microservices-preface-by-tr ...
- CentOS7安装CDH 第九章:CDH中安装Kafka
相关文章链接 CentOS7安装CDH 第一章:CentOS7系统安装 CentOS7安装CDH 第二章:CentOS7各个软件安装和启动 CentOS7安装CDH 第三章:CDH中的问题和解决方法 ...
- ASP.NET Core的路由[1]:注册URL模式与HttpHandler的映射关系
ASP.NET Core的路由是通过一个类型为RouterMiddleware的中间件来实现的.如果我们将最终处理HTTP请求的组件称为HttpHandler,那么RouterMiddleware中间 ...
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第六章:管理产品图片——多对多关系(上篇)
在这章中,我们将学习如何创建一个管理图片的新实体,如何使用HTML表单上传图片文件,并使用多对多关系将它们和产品关联起来,如何将图片存储在文件系统中.在这章中,我们还会学习更加复杂的异常处理,如何向模 ...
- EF Core中如何设置数据库表自己与自己的多对多关系
本文的代码基于.NET Core 3.0和EF Core 3.0 有时候在数据库设计中,一个表自己会和自己是多对多关系. 在SQL Server数据库中,现在我们有Person表,代表一个人,建表语句 ...
- 【无私分享:ASP.NET CORE 项目实战(第二章)】添加EF上下文对象,添加接口、实现类以及无处不在的依赖注入(DI)
目录索引 [无私分享:ASP.NET CORE 项目实战]目录索引 简介 上一章,我们介绍了安装和新建控制器.视图,这一章我们来创建个数据模型,并且添加接口和实现类. 添加EF上下文对象 按照我们以前 ...
随机推荐
- Java 读书笔记 (十一) Number & Math 类
所有的包装类(Integer.Long.Byte.Double.Float.Short)都是抽象类Number的子类. 这种由编译器特别支持的包装称为装箱,所以当内置数据类型被当作对象使用的时候,编译 ...
- 关于find命令的一些知识
在服务器运维的过程中,我们会用到这样一个命令,关于这个命令,你知道多少呢?接下来,咱们一起来研究一下它的用途. find命令主要用来在硬盘上搜索文件, find命令主要用于文件查找,列出当前目录及子目 ...
- go语言nsq源码解读二 nsqlookupd、nsqd与nsqadmin
nsqlookupd: 官方文档解释见:http://bitly.github.io/nsq/components/nsqlookupd.html 用官方话来讲是:nsqlookupd管理拓扑信息,客 ...
- 解锁 vmware esxi 6.7 并安装 mac os 10.13
1.安装 esxi 6.7 2.下载 unlocker 2.1.1.zip 3.上传 unlocker 2.1.1.zip esxi的磁盘中 4.开启esxi的ssh登录 5.使用 ssh 登录 es ...
- 【bzoj 3131】[Sdoi2013]淘金
Description 小Z在玩一个叫做<淘金者>的游戏.游戏的世界是一个二维坐标.X轴.Y轴坐标范围均为1..N.初始的时候,所有的整数坐标点上均有一块金子,共N*N块. 一阵风吹 ...
- BZOJ_1705_[Usaco2007 Nov]Telephone Wire 架设电话线_DP
BZOJ_1705_[Usaco2007 Nov]Telephone Wire 架设电话线_DP Description 最近,Farmer John的奶牛们越来越不满于牛棚里一塌糊涂的电话服务 于是 ...
- [Usaco2009 Jan]安全路经Travel BZOJ1576 Dijkstra+树链剖分+线段树
分析: Dijkstra求最短路树,在最短路树上进行操作,详情可见上一篇博客:http://www.cnblogs.com/Winniechen/p/9042937.html 我觉得这个东西不压行写出 ...
- Charpter3 名字 作用域 约束
一个对象拥有其语义价值的区域<其作用域 当一个变量将不再被使用,那它应该被理想的回收机制回收.但现实是我们仅当一个变量离开了其作用域,或变成不可访问,才考虑回收. 然而,作用域规则有其优点:1. ...
- Android 7.0 存储系统—Vold与MountService分析(一)(转 Android 9.0 分析)
Android的存储系统(一) 看了很长时间Vold存储模块的相关知识,也死扣了一段时间的Android源码,发现Android存储系统所涉及的函数调用,以及Kernel与上层之间的Socket传输真 ...
- safari 浏览器 input textarea select 等不能响应用户输入
解决办法 -webkit-user-select:auto; /*webkit浏览器*/ user-select:auto; -o-user-select:auto; -ms-user-select: ...