- GraphQL نیازمند رفت و برگشتهای کمتری به server، به منظور بازیابی دادهها برای template یا view است. همراه با REST ما مجبور هستیم که چندیدن endpoint مثلا (... api/students, api/courses, api/instructors ) را برای گرفتن همه دادههای که برای template یا view نیاز داریم ملاقات کنیم؛ ولی این شرایط در GraphQL برقرار نیست. با GraphQL ما تنها یک query را ایجاد میکنیم که چندین تابع (resolver) را در سمت سرور فراخوانی میکند و همه دادهها را از منابع مختلفی، در یک درخواست برگشت میدهد.
- همراه با REST، همانطور که Application ما رشد میکند، تعداد endpointها هم زیاد میشوند که این نیازمند زمان بیشتری برای نگهداری میباشد. اما با GraphQL ما تنها یک endpoint داریم؛ همین!
- با استفاده از GraphQL، ما هرگز به مشکل گرفتن دادههایی کم یا زیاد از منبع روبرو نخواهیم شد. به این خاطر است که ما queryها را با فیلدهایی که چیزهایی را که نیاز داریم، نشان میدهند، تعریف میکنیم. در این صورت ما همیشه چیزهایی را که درخواست دادهایم، دریافت میکنیم.
query OwnersQuery { owners { name account { type } } }
{ "data": { "owners": [ { "name": "John Doe", "accounts": [ { "type": "Cash" }, { "type": "Savings" } ] } ] } }
dotnet new api -n ASPCoreGraphQL
پوشه Contracts شامل واسطهای مورد نیاز برای repository logic میباشد:
namespace ASPCoreGraphQL.Contracts { public interface IOwnerRepository { } }
namespace ASPCoreGraphQL.Contracts { public interface IAccountRepository { } }
public class Owner { [Key] public Guid Id { get; set; } [Required(ErrorMessage = "Name is required")] public string Name { get; set; } public string Address { get; set; } public ICollection<Account> Accounts { get; set; } } public class Account { [Key] public Guid Id { get; set; } [Required(ErrorMessage = "Type is required")] public TypeOfAccount Type { get; set; } public string Description { get; set; } [ForeignKey("OwnerId")] public Guid OwnerId { get; set; } public Owner Owner { get; set; } } public enum TypeOfAccount { Cash, Savings, Expense, Income }
public class ApplicationContext : DbContext { public ApplicationContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { } public DbSet<Owner> Owners { get; set; } public DbSet<Account> Accounts { get; set; } }
public class OwnerRepository : IOwnerRepository { private readonly ApplicationContext _context; public OwnerRepository(ApplicationContext context) { _context = context; } }
public class AccountRepository : IAccountRepository { private readonly ApplicationContext _context; public AccountRepository(ApplicationContext context) { _context = context; } }
public void ConfigureServices(IServiceCollection services) { services.AddDbContext<ApplicationContext>(opt => opt.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddScoped<IOwnerRepository, OwnerRepository>(); services.AddScoped<IAccountRepository, AccountRepository>(); services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2) .AddJsonOptions(options => options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore); }
dotnet add package GraphQL
dotnet add package GraphQL.Server.Transports.AspNetCore
dotnet add package GraphQL.Server.Ui.Playground
public class AppSchema : Schema { public AppSchema(IDependencyResolver resolver) :base(resolver) { } }
public class OwnerType : ObjectGraphType<Owner> { public OwnerType() { Field(x => x.Id, type: typeof(IdGraphType)).Description("Id property from the owner object."); Field(x => x.Name).Description("Name property from the owner object."); Field(x => x.Address).Description("Address property from the owner object."); } }
public interface IOwnerRepository { IEnumerable<Owner> GetAll(); } public class OwnerRepository : IOwnerRepository { private readonly ApplicationContext _context; public OwnerRepository(ApplicationContext context) { _context = context; } public IEnumerable<Owner> GetAll() => _context.Owners.ToList(); }
public class AppQuery : ObjectGraphType { public AppQuery(IOwnerRepository repository) { Field<ListGraphType<OwnerType>>( "owners", resolve: context => repository.GetAll() ); } }
public class AppSchema : Schema { public AppSchema(IDependencyResolver resolver) :base(resolver) { Query = resolver.Resolve<AppQuery>(); } }
public void ConfigureServices(IServiceCollection services) { ... services.AddScoped<IDependencyResolver>(s => new FuncDependencyResolver(s.GetRequiredService)); services.AddScoped<AppSchema>(); services.AddGraphQL(o => { o.ExposeExceptions = false; }) .AddGraphTypes(ServiceLifetime.Scoped); ... }
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { ... app.UseGraphQL<AppSchema>(); app.UseGraphQLPlayground(options: new GraphQLPlaygroundOptions()); app.UseMvc(); }
dotnet run
https://localhost:5001/ui/playground