GraphQL在.NET?8中的全面實(shí)踐指南(最新推薦)
一、GraphQL與.NET 8概述
GraphQL是一種由Facebook開(kāi)發(fā)的API查詢語(yǔ)言,它提供了一種更高效、更靈活的替代REST的方案。與REST不同,GraphQL允許客戶端精確指定需要的數(shù)據(jù)結(jié)構(gòu)和字段,避免了"過(guò)度獲取"或"不足獲取"的問(wèn)題。
.NET 8對(duì)GraphQL的支持
.NET 8帶來(lái)了多項(xiàng)性能改進(jìn)和新特性,使其成為構(gòu)建GraphQL服務(wù)的理想平臺(tái):
- 性能提升:AOT編譯、改進(jìn)的JIT編譯器
- 最小API增強(qiáng):簡(jiǎn)化GraphQL端點(diǎn)設(shè)置
- 原生AOT支持:適合云原生GraphQL服務(wù)部署
- 改進(jìn)的依賴注入:更簡(jiǎn)潔的服務(wù)注冊(cè)方式
二、環(huán)境準(zhǔn)備與項(xiàng)目搭建
1. 創(chuàng)建.NET 8項(xiàng)目
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
三、基礎(chǔ)GraphQL服務(wù)搭建
1. 定義數(shù)據(jù)模型
// 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. 注冊(cè)GraphQL服務(wù)
// Program.cs var builder = WebApplication.CreateBuilder(args); // 添加DbContext builder.Services.AddDbContext<AppDbContext>(options => options.UseSqlServer(builder.Configuration.GetConnectionString("DefaultConnection"))); // 添加GraphQL服務(wù) builder.Services .AddGraphQLServer() .AddQueryType<Query>() .AddMutationType<Mutation>() .AddProjections() .AddFiltering() .AddSorting(); var app = builder.Build(); app.MapGraphQL(); // 默認(rèn)路徑為/graphql app.Run();
四、查詢(Query)實(shí)現(xiàn)
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. 復(fù)雜查詢示例
query { books(where: { title: { contains: "NET" } }, order: { publishedDate: DESC }) { title publishedDate author { name } } }
五、變更(Mutation)實(shí)現(xiàn)
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 } } }
六、高級(jí)特性實(shí)現(xiàn)
1. 數(shù)據(jù)加載器(DataLoader)優(yōu)化
// 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); }); // 假設(shè)我們有一些作者ID var authorIds = new[] { 1, 2, 3 }; return await loader.LoadAsync(authorIds); }
2. 訂閱(Subscription)實(shí)現(xiàn)
// GraphQL/Subscription.cs [ExtendObjectType("Subscription")] public class BookSubscriptions { [Subscribe] [Topic("BookAdded")] public Book OnBookAdded([EventMessage] Book book) => book; } // 在Mutation中發(fā)布事件 [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); }
七、性能優(yōu)化與安全
1. 查詢復(fù)雜度分析
builder.Services .AddGraphQLServer() .AddQueryType<Query>() .AddMutationType<Mutation>() .AddMaxExecutionDepthRule(5) // 限制查詢深度 .AddQueryCostOptions(options => { options.DefaultCost = 1; options.MaxAllowedCost = 1000; });
2. 認(rèn)證與授權(quán)
// 添加認(rèn)證服務(wù) builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { /* 配置JWT */ }); // 保護(hù)GraphQL端點(diǎn) builder.Services .AddGraphQLServer() .AddAuthorization() .AddHttpRequestInterceptor<AuthInterceptor>(); // 實(shí)現(xiàn)攔截器 public class AuthInterceptor : DefaultHttpRequestInterceptor { public override ValueTask OnCreateAsync( HttpContext context, IRequestExecutor requestExecutor, IQueryRequestBuilder requestBuilder, CancellationToken cancellationToken) { if (!context.User.Identity.IsAuthenticated) { throw new GraphQLException("未認(rèn)證用戶"); } return base.OnCreateAsync(context, requestExecutor, requestBuilder, cancellationToken); } }
八、.NET 8特有優(yōu)化
1. AOT編譯支持
<PropertyGroup> <PublishAot>true</PublishAot> </PropertyGroup>
2. 最小API集成
app.MapGraphQL() .WithTags("GraphQL") .WithDescription("GraphQL API端點(diǎn)") .RequireAuthorization();
3. 性能監(jiān)控
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($"請(qǐng)求處理時(shí)間: {stopwatch.ElapsedMilliseconds}ms"); } }
九、測(cè)試GraphQL API
1. 使用Banana Cake Pop
HotChocolate內(nèi)置了Banana Cake Pop這個(gè)GraphQL IDE,訪問(wèn)/graphql
即可使用。
2. 單元測(cè)試示例
[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(); // 執(zhí)行 var result = await executor.ExecuteAsync(@" query { books { title author { name } } }"); // 斷言 Assert.IsFalse(result.Errors?.Any() ?? false); var books = result.ToJson(); Assert.IsNotNull(books); } }
十、部署與擴(kuò)展
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. 擴(kuò)展架構(gòu)建議
- 聯(lián)邦架構(gòu):使用HotChocolate Federation擴(kuò)展
- 緩存策略:實(shí)現(xiàn)查詢緩存中間件
- 限流:添加請(qǐng)求限流保護(hù)
結(jié)語(yǔ)
.NET 8為構(gòu)建高性能GraphQL服務(wù)提供了堅(jiān)實(shí)的基礎(chǔ),結(jié)合HotChocolate這樣的成熟庫(kù),開(kāi)發(fā)者可以快速構(gòu)建靈活、高效的API服務(wù)。本文涵蓋了從基礎(chǔ)到高級(jí)的各個(gè)方面,希望能幫助您在.NET生態(tài)中充分利用GraphQL的優(yōu)勢(shì)。
實(shí)際項(xiàng)目中,建議根據(jù)具體需求選擇合適的GraphQL特性,平衡靈活性與性能,并始終關(guān)注API的安全性和可維護(hù)性
到此這篇關(guān)于GraphQL在.NET 8中的全面實(shí)踐指南(最新推薦)的文章就介紹到這了,更多相關(guān)GraphQL .NET實(shí)踐內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
基于.NET Core 3.1 網(wǎng)站開(kāi)發(fā)和部署的方法
這篇文章主要介紹了基于.NET Core 3.1 網(wǎng)站開(kāi)發(fā)和部署的方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08asp.net中生成縮略圖并添加版權(quán)實(shí)例代碼
這篇文章介紹了asp.net中生成縮略圖并添加版權(quán)實(shí)例代碼,有需要的朋友可以參考一下2013-11-11.NET 6開(kāi)發(fā)TodoList應(yīng)用之實(shí)現(xiàn)接口請(qǐng)求驗(yàn)證
在響應(yīng)請(qǐng)求處理的過(guò)程中,我們經(jīng)常需要對(duì)請(qǐng)求參數(shù)的合法性進(jìn)行校驗(yàn),如果參數(shù)不合法,將不繼續(xù)進(jìn)行業(yè)務(wù)邏輯的處理。本文將介紹如何使用FluentValidation和MediatR實(shí)現(xiàn)接口請(qǐng)求驗(yàn)證,需要的可以參考一下2021-12-12ASP.NET網(wǎng)站第一次訪問(wèn)慢的解決方法
這篇文章主要為大家詳細(xì)介紹了IIS8上ASP.NET第一次訪問(wèn)慢的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-04-04Visual Studio卸載不完全問(wèn)題的解決方法
這篇文章主要為大家詳細(xì)介紹了Visual Studio卸載不完全問(wèn)題的解決方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04.net Core連接MongoDB數(shù)據(jù)庫(kù)的步驟詳解
這篇文章主要給大家介紹了關(guān)于.net Core連接MongoDB數(shù)據(jù)庫(kù)步驟的相關(guān)資料,文中將實(shí)現(xiàn)的步驟一步步介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-02-02