
离线 TA的专栏
- 打卡等级:热心大叔
- 打卡总天数:232
- 打卡月天数:0
- 打卡总奖励:4028
- 最近打卡:2025-08-02 15:22:28
|
一、GraphQL与.NET 8概述
GraphQL是一种由Facebook开发的API查询语言,它提供了一种更高效、更灵活的替代REST的方案。与REST不同,GraphQL允许客户端精确指定需要的数据结构和字段,避免了"过度获取"或"不足获取"的问题。
.NET 8对GraphQL的支持
.NET 8带来了多项性能改进和新特性,使其成为构建GraphQL服务的理想平台:
- 性能提升:AOT编译、改进的JIT编译器
- 最小API增强:简化GraphQL端点设置
- 原生AOT支持:适合云原生GraphQL服务部署
- 改进的依赖注入:更简洁的服务注册方式
二、环境准备与项目搭建
1. 创建.NET 8项目
- dotnet new web -n GraphQLDemo
- cd GraphQLDemo
复制代码
2. 添加必要的NuGet包
- dotnet add package HotChocolate.AspNetCore
- dotnet add package HotChocolate.Data
- dotnet add package Microsoft.EntityFrameworkCore.SqlServer
复制代码
三、基础GraphQL服务搭建
1. 定义数据模型
- // Models/Book.cs
- public class Book
- {
- public int Id { get; set; }
- public string Title { get; set; }
- public Author Author { get; set; }
- public DateTime PublishedDate { get; set; }
- }
- // Models/Author.cs
- public class Author
- {
- public int Id { get; set; }
- public string Name { get; set; }
- public ICollection<Book> Books { get; set; } = new List<Book>();
- }
复制代码
2. 配置DbContext
- // Data/AppDbContext.cs
- public class AppDbContext : DbContext
- {
- public AppDbContext(DbContextOptions<AppDbContext> options)
- : base(options) { }
- public DbSet<Book> Books { get; set; }
- public DbSet<Author> Authors { get; set; }
- protected override void OnModelCreating(ModelBuilder modelBuilder)
- {
- modelBuilder.Entity<Author>()
- .HasMany(a => a.Books)
- .WithOne(b => b.Author)
- .HasForeignKey(b => b.AuthorId);
- }
- }
复制代码
3. 注册GraphQL服务
- // Program.cs
- var builder = WebApplication.CreateBuilder(args);
- // 添加DbContext
- builder.Services.AddDbContext<AppDbContext>(options =>
- options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection")));
- // 添加GraphQL服务
- builder.Services
- .AddGraphQLServer()
- .AddQueryType<Query>()
- .AddMutationType<Mutation>()
- .AddProjections()
- .AddFiltering()
- .AddSorting();
- var app = builder.Build();
- app.MapGraphQL(); // 默认路径为/graphql
- app.Run();
复制代码
四、查询(Query)实现
1. 基本查询类型
- // GraphQL/Query.cs
- public class Query
- {
- [UseDbContext(typeof(AppDbContext))]
- [UseProjection]
- [UseFiltering]
- [UseSorting]
- public IQueryable<Book> GetBooks([ScopedService] AppDbContext context)
- => context.Books;
- [UseDbContext(typeof(AppDbContext))]
- public async Task<Book?> GetBookById(
- [ScopedService] AppDbContext context,
- int id)
- => await context.Books.FindAsync(id);
- }
复制代码
2. 复杂查询示例
- query {
- books(where: { title: { contains: "NET" } }, order: { publishedDate: DESC }) {
- title
- publishedDate
- author {
- name
- }
- }
- }
复制代码
五、变更(Mutation)实现
1. 基本变更操作
- // GraphQL/Mutation.cs
- public class Mutation
- {
- [UseDbContext(typeof(AppDbContext))]
- public async Task<AddBookPayload> AddBook(
- AddBookInput input,
- [ScopedService] AppDbContext context)
- {
- var book = new Book
- {
- Title = input.Title,
- PublishedDate = input.PublishedDate,
- AuthorId = input.AuthorId
- };
- context.Books.Add(book);
- await context.SaveChangesAsync();
- return new AddBookPayload(book);
- }
- }
- public record AddBookInput(string Title, DateTime PublishedDate, int AuthorId);
- public record AddBookPayload(Book Book);
复制代码
2. 输入类型与Payload模式
- mutation {
- addBook(input: {
- title: "Mastering GraphQL in .NET 8",
- publishedDate: "2023-11-01",
- authorId: 1
- }) {
- book {
- id
- title
- }
- }
- }
复制代码
六、高级特性实现
1. 数据加载器(DataLoader)优化
- // GraphQL/Query.cs
- public async Task<IEnumerable<Author>> GetAuthorsWithBooks(
- [Service] AppDbContext context,
- [Service] IResolverContext resolverContext)
- {
- var loader = resolverContext.BatchDataLoader<int, Author>(
- "authorsById",
- async (ids, ct) =>
- {
- var authors = await context.Authors
- .Where(a => ids.Contains(a.Id))
- .ToDictionaryAsync(a => a.Id, ct);
- return ids.Select(id => authors.TryGetValue(id, out var author) ? author : null);
- });
- // 假设我们有一些作者ID
- var authorIds = new[] { 1, 2, 3 };
- return await loader.LoadAsync(authorIds);
- }
复制代码
2. 订阅(Subscription)实现
- // GraphQL/Subscription.cs
- [ExtendObjectType("Subscription")]
- public class BookSubscriptions
- {
- [Subscribe]
- [Topic("BookAdded")]
- public Book OnBookAdded([EventMessage] Book book) => book;
- }
- // 在Mutation中发布事件
- [UseDbContext(typeof(AppDbContext))]
- public async Task<AddBookPayload> AddBook(
- AddBookInput input,
- [ScopedService] AppDbContext context,
- [Service] ITopicEventSender eventSender)
- {
- var book = new Book { /* ... */ };
- context.Books.Add(book);
- await context.SaveChangesAsync();
- await eventSender.SendAsync("BookAdded", book);
- return new AddBookPayload(book);
- }
复制代码
七、性能优化与安全
1. 查询复杂度分析
- builder.Services
- .AddGraphQLServer()
- .AddQueryType<Query>()
- .AddMutationType<Mutation>()
- .AddMaxExecutionDepthRule(5) // 限制查询深度
- .AddQueryCostOptions(options =>
- {
- options.DefaultCost = 1;
- options.MaxAllowedCost = 1000;
- });
复制代码
2. 认证与授权
- // 添加认证服务
- builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
- .AddJwtBearer(options => { /* 配置JWT */ });
- // 保护GraphQL端点
- builder.Services
- .AddGraphQLServer()
- .AddAuthorization()
- .AddHttpRequestInterceptor<AuthInterceptor>();
- // 实现拦截器
- public class AuthInterceptor : DefaultHttpRequestInterceptor
- {
- public override ValueTask OnCreateAsync(
- HttpContext context,
- IRequestExecutor requestExecutor,
- IQueryRequestBuilder requestBuilder,
- CancellationToken cancellationToken)
- {
- if (!context.User.Identity.IsAuthenticated)
- {
- throw new GraphQLException("未认证用户");
- }
- return base.OnCreateAsync(context, requestExecutor, requestBuilder, cancellationToken);
- }
- }
复制代码
八、.NET 8特有优化
1. AOT编译支持
- <PropertyGroup>
- <PublishAot>true</PublishAot>
- </PropertyGroup>
复制代码
2. 最小API集成
- app.MapGraphQL()
- .WithTags("GraphQL")
- .WithDescription("GraphQL API端点")
- .RequireAuthorization();
复制代码
3. 性能监控
- builder.Services
- .AddGraphQLServer()
- .AddInstrumentation(options =>
- {
- options.RequestDetails = RequestDetails.All;
- options.IncludeDocument = true;
- })
- .AddDiagnosticEventListener<PerformanceLogger>();
- public class PerformanceLogger : DiagnosticEventListener
- {
- public override void RequestProcessing(HttpContext context, IRequestExecutor executor, IQueryRequest request)
- {
- var stopwatch = Stopwatch.StartNew();
- base.RequestProcessing(context, executor, request);
- stopwatch.Stop();
- Console.WriteLine($"请求处理时间: {stopwatch.ElapsedMilliseconds}ms");
- }
- }
复制代码
九、测试GraphQL API
1. 使用Banana Cake Pop
HotChocolate内置了Banana Cake Pop这个GraphQL IDE,访问 即可使用。
2. 单元测试示例
- [TestClass]
- public class GraphQLTests
- {
- [TestMethod]
- public async Task GetBooks_ReturnsValidData()
- {
- // 安排
- var executor = await new ServiceCollection()
- .AddGraphQLServer()
- .AddQueryType<Query>()
- .AddDbContext<AppDbContext>(options =>
- options.UseInMemoryDatabase("TestDB"))
- .BuildRequestExecutorAsync();
- // 执行
- var result = await executor.ExecuteAsync(@"
- query {
- books {
- title
- author {
- name
- }
- }
- }");
- // 断言
- Assert.IsFalse(result.Errors?.Any() ?? false);
- var books = result.ToJson();
- Assert.IsNotNull(books);
- }
- }
复制代码
十、部署与扩展
1. 容器化部署
- FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
- WORKDIR /src
- COPY . .
- RUN dotnet publish -c Release -o /app /p:PublishAot=true
- FROM mcr.microsoft.com/dotnet/aspnet:8.0
- WORKDIR /app
- COPY --from=build /app .
- ENTRYPOINT ["./GraphQLDemo"]
复制代码
2. 扩展架构建议
- 联邦架构:使用HotChocolate Federation扩展
- 缓存策略:实现查询缓存中间件
- 限流:添加请求限流保护
结语
.NET 8为构建高性能GraphQL服务提供了坚实的基础,结合HotChocolate这样的成熟库,开发者可以快速构建灵活、高效的API服务。本文涵盖了从基础到高级的各个方面,希望能帮助您在.NET生态中充分利用GraphQL的优势。
实际项目中,建议根据具体需求选择合适的GraphQL特性,平衡灵活性与性能,并始终关注API的安全性和可维护性
到此这篇关于GraphQL在.NET 8中的全面实践指南(最新推荐)的文章就介绍到这了,更多相关GraphQL .NET实践内容请搜索晓枫资讯以前的文章或继续浏览下面的相关文章希望大家以后多多支持晓枫资讯! 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |
晓枫资讯-科技资讯社区-免责声明
免责声明:以上内容为本网站转自其它媒体,相关信息仅为传递更多信息之目的,不代表本网观点,亦不代表本网站赞同其观点或证实其内容的真实性。
1、注册用户在本社区发表、转载的任何作品仅代表其个人观点,不代表本社区认同其观点。
2、管理员及版主有权在不事先通知或不经作者准许的情况下删除其在本社区所发表的文章。
3、本社区的文章部分内容可能来源于网络,仅供大家学习与参考,如有侵权,举报反馈:  进行删除处理。
4、本社区一切资源不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
5、以上声明内容的最终解释权归《晓枫资讯-科技资讯社区》所有。
|