到目前为止我们一直在使用GraphQL操作单个实体。在本篇博文中,我们将使用GraphQL操作实体集合。
这里我们使用的场景是处理一个顾客的所有订单,顾客和订单之间的关系是一对多。一个顾客可以有多个订单,相应的一个订单只属于一个顾客。
数据库修改下面我们首先创建2个新的类Customer和Order。
Customerpublic class Customer{ public int CustomerId { get; set; } public string Name { get; set; } public string BillingAddress { get; set; } public IEnumerable Orders { get; set; }
} Orderpublic 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; }
}然后我们修改ApplicationDbContext类,在OnModelCreating配置一下表的主外键。
modelBuilder.Entity() .HasKey(p => p.CustomerId); modelBuilder.Entity ().HasMany(p => p.Orders) .WithOne() .HasForeignKey(p => p.CustomerId); modelBuilder.Entity ().HasKey(p => p.OrderId);
最后我们使用如下命令创建迁移并更新数据库
dotnet ef migrations add OneToManyRelationship dotnet ef database update
至此数据库修改完成。
添加GraphQL代码下面我们需要添加GraphQL针对Customer和Order表的字段配置。
OrderTypepublic class OrderType: ObjectGraphTypeCustomerType.cs{ public OrderType(IDataStore dataStore) { Field(o => o.Tag); Field(o => o.CreatedAt); Field () .Name("Customer") .ResolveAsync(ctx => { return dataStore.GetCustomerByIdAsync(ctx.Source.CustomerId); }); } }
public class CustomerType: ObjectGraphType{ public CustomerType(IDataStore dataStore) { Field(c => c.Name); Field(c => c.BillingAddress); Field , IEnumerable > () .Name("Orders") .ResolveAsync(ctx => { return dataStore.GetOrdersByCustomerIdAsync(ctx.Source.CustomerId); }); } }
为了查询所有的顾客和订单,我们还需要暴露出2个新的节点。所以我们修改在InventoryQuery构造函数中添加如下代码:
InventoryQueryField, IEnumerable >() .Name("Orders") .ResolveAsync(ctx => { return dataStore.GetOrdersAsync(); }); Field , IEnumerable >() .Name("Customers") .ResolveAsync(ctx => { return dataStore.GetCustomersAsync(); });
然后我们需要在IDataStore中定义6个新的方法,并在DataStore中实现它们。
IDataStoreTaskDataStore> GetOrdersAsync(); Task > GetCustomersAsync(); Task GetCustomerByIdAsync(int customerId); Task > GetOrdersByCustomerIdAsync(int customerId); Task AddOrderAsync(Order order); Task AddCustomerAsync(Customer customer);
public async Task> GetOrdersAsync() { return await _context.Orders .AsNoTracking() .ToListAsync(); }public async Task > GetCustomersAsync() { return await _context.Customers .AsNoTracking() .ToListAsync(); }public async Task GetCustomerByIdAsync(int customerId){ return await _context.Customers .FindAsync(customerId); }public async Task > GetOrdersByCustomerIdAsync(int customerId) { return await _context.Orders .Where(o => o.CustomerId == customerId) .ToListAsync(); }public async Task AddOrderAsync(Order order) { var addedOrder = await _context.Orders.AddAsync(order); await _context.SaveChangesAsync(); return addedOrder.Entity; }public async Task AddCustomerAsync(Customer customer) { var addedCustomer = await _context.Customers.AddAsync(customer); await _context.SaveChangesAsync(); return addedCustomer.Entity; }
添加完以上代码之后,我们就需要定义添加订单和顾客的输入类型了。还记得在上一章中我们如何添加货物的么?我们添加了一个ItemInputType类,定义了添加货物需要收集的字段,所以这里同理,我们也需要为订单和顾客定义对应的InputObjectGraphType。
OrderInputTypepublic class OrderInputType : InputObjectGraphType {
public OrderInputType()
{
Name = "OrderInput";
Field>("tag");
Field>("createdAt");
Field>("customerId");
}
} CustomerInputTypepublic class CustomerInputType : InputObjectGraphType {
public CustomerInputType()
{
Name = "CustomerInput";
Field>("name");
Field>("billingAddress");
}
} 当前添加以上代码之后,我们还需要在Startup类中注册这几个新类型
public void ConfigureServices(IServiceCollection services)
{
....
....
services.AddScoped();
services.AddScoped();
services.AddScoped();
services.AddScoped();
} 如果现在启动项目,你会得到以下错误
Failed to call Activator.CreateInstance. Type: chapter1.OrderType
这里的问题是在InventorySchema构造函数中的注入没起作用, 原因是GraphQL在解决依赖的时候,只能处理一层, 这里OrderType和CustomerType是2层的关系。如果想解决这个问题,我们需要在Startup中再注册一个依赖解决器。
services.AddScoped(s => new FuncDependencyResolver(s.GetRequiredService));
修改完成之后我们还需要修改InventorySchema, 在构造函数中将依赖解决器注入。
public class InventorySchema: Schema {
public InventorySchema(IDependencyResolver resolver): base(resolver) {
Query = resolver.Resolve();
Mutation = resolver.Resolve();
}
} 现在再次启动项目,程序不报错了。
最终效果下面我们首先创建一个Customer
然后我们继续创建2个Order
最后我们来查询一下刚才创建的数据是否存在
数据读取正确,这说明我们的数据添加成功了。
本文源代码: https://github.com/lamondlu/GraphQL_Blogs/tree/master/Part%20VIII
作者:Lamond Lu
出处:https://www.cnblogs.com/lwqlun/p/9949559.html



