栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

ASP.NET Core中使用GraphQL

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ASP.NET Core中使用GraphQL

到目前为止我们一直在使用GraphQL操作单个实体。在本篇博文中,我们将使用GraphQL操作实体集合。

这里我们使用的场景是处理一个顾客的所有订单,顾客和订单之间的关系是一对多。一个顾客可以有多个订单,相应的一个订单只属于一个顾客。

数据库修改

下面我们首先创建2个新的类Customer和Order。

Customer
public class Customer{    public int CustomerId { get; set; }    public string Name { get; set; }    public string BillingAddress { get; set; }    public IEnumerable Orders { get; set; }
}
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; }
}

然后我们修改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表的字段配置。

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);
            });
    }
}
CustomerType.cs
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构造函数中添加如下代码:

InventoryQuery
Field, IEnumerable>()  
    .Name("Orders")
    .ResolveAsync(ctx =>
    {        return dataStore.GetOrdersAsync();
    });

Field, IEnumerable>()  
    .Name("Customers")
    .ResolveAsync(ctx =>
    {        return dataStore.GetCustomersAsync();
    });

然后我们需要在IDataStore中定义6个新的方法,并在DataStore中实现它们。

IDataStore
Task> GetOrdersAsync();

Task> GetCustomersAsync();

Task GetCustomerByIdAsync(int customerId);

Task> GetOrdersByCustomerIdAsync(int customerId);

Task AddOrderAsync(Order order);

Task AddCustomerAsync(Customer customer);
DataStore
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。

OrderInputType
public class OrderInputType : InputObjectGraphType {  
    public OrderInputType()
    {
        Name = "OrderInput";
        Field>("tag");
        Field>("createdAt");
        Field>("customerId");
    }
}
CustomerInputType
public 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


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/231141.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号