### GraphQL.NET Code-First Approach Example Source: https://github.com/shane32/graphql.di/blob/master/README.md This C# example illustrates the traditional code-first approach in GraphQL.NET using ObjectGraphType. It shows how to define fields and resolve relationships, including an example of resolving a scoped service from the context. ```csharp public class TodoType : ObjectGraphType { public TodoType() { Field(x => x.Id); Field(x => x.Title); Field("completedBy") .Resolve(context => { var repository = context.RequestServices!.GetRequiredService(); return repository.GetPersonById(context.Source.CompletedByPersonId); }); } } ``` -------------------------------- ### Install GraphQL.DI NuGet Package Source: https://context7.com/shane32/graphql.di/llms.txt This command installs the necessary GraphQL.DI NuGet package for your .NET project. Ensure you are in the project directory when running this command. ```bash dotnet add package Shane32.GraphQL.DI ``` -------------------------------- ### GraphQL.NET Type-First Approach Example Source: https://github.com/shane32/graphql.di/blob/master/README.md This C# snippet demonstrates GraphQL.NET's type-first approach, where the schema is inferred from C# models. It shows how to include a method with a service injection for resolving a related object. ```csharp public class Todo { public int Id { get; set; } public string Title { get; set; } [Ignore] public int CompletedByPersonId { get; set; } public Person CompletedBy([FromServices] IRepository repository) => repository.GetPersonById(CompletedByPersonId); } ``` -------------------------------- ### GraphQL.DI: Accessing Source Object in Resolvers (C#) Source: https://github.com/shane32/graphql.di/blob/master/README.md Provides examples of various ways to access the source object within GraphQL.DI resolvers. This includes using a 'source' argument, IResolveFieldContext, the [FromSource] attribute, the Source property, and the Context property. ```csharp // Access source by an argument named "source" with correct type public static int Id(Todo source) => source.Id; // Access source via IResolveFieldContext public static int Id(IResolveFieldContext context) => ((Todo)context.Source).Id; // Access source using [FromSource] public static int Id([FromSource] Todo obj) => obj.Id; // Access source using Source property public int Id() => Source.Id; // Access source using Context property public int Id() => ((Todo)Context.Source).Id; ``` -------------------------------- ### Implement GraphQL Mutations with DIObjectGraphBase in C# Source: https://github.com/shane32/graphql.di/blob/master/README.md Demonstrates how to define a root mutation type by inheriting from DIObjectGraphBase. This example shows adding a new todo item and marking an existing todo item as complete, including dependency injection for data repository access and cancellation token support. ```csharp public class Mutation : DIObjectGraphBase { private readonly IRepository _repository; public Mutation(IRepository repository) { _repository = repository; } public async Task AddTodoAsync(string title, string notes) { // Use RequestAborted for cancellation support var todo = new Todo { Title = title, Notes = notes, }; return await _repository.AddTodoAsync(todo, RequestAborted); } public async Task SetCompleteAsync(int id, int completedByPersonId) { var todo = await _repository.GetTodoAsync(id, RequestAborted); if (todo == null) return null; if (todo.Completed) throw new ExecutionError($"Task id {id} has already been completed"); todo.Completed = true; todo.CompletedByPersonId = completedByPersonId; todo.CompletionDate = DateTime.Now; await _repository.SaveChangesAsync(RequestAborted); return todo; } } ``` -------------------------------- ### Implement GraphQL Mutations with DI and Error Handling Source: https://context7.com/shane32/graphql.di/llms.txt Defines C# classes for GraphQL mutation types, demonstrating how to integrate with a database context for data modification. Includes examples for adding, deleting, and updating todos, with specific error handling for GraphQL execution errors. ```csharp // Mutation graph type definition public class MutationType : DIObjectGraphType { } // Mutation resolver with DI public class Mutation : DIObjectGraphBase { private readonly TodoDbContext _db; public Mutation(TodoDbContext db) { _db = db; } // Create mutation public async Task AddTodoAsync(string title, string notes, CancellationToken cancellationToken) { var todo = new Todo { Title = title, Notes = notes, }; _db.Add(todo); await _db.SaveChangesAsync(cancellationToken); return todo; } // Delete mutation public async Task DeleteTodoAsync(int id, CancellationToken cancellationToken) { var todo = await _db.Set() .Where(x => x.Id == id) .SingleOrDefaultAsync(cancellationToken); if (todo == null) return false; _db.Set().Remove(todo); await _db.SaveChangesAsync(cancellationToken); return true; } // Update mutation with error handling public async Task SetCompleteAsync(int id, int completedByPersonId, CancellationToken cancellationToken) { var todo = await _db.Set() .Where(x => x.Id == id) .SingleOrDefaultAsync(cancellationToken); if (todo == null) return null; // Throw ExecutionError for GraphQL-specific errors if (todo.Completed) throw new ExecutionError($"Task id {id} has already been completed"); todo.Completed = true; todo.CompletedByPersonId = completedByPersonId; todo.CompletionDate = DateTime.Now; await _db.SaveChangesAsync(cancellationToken); return todo; } } // GraphQL mutation examples: // mutation { addTodo(title: "New Task", notes: "Description") { id title } } // mutation { deleteTodo(id: 1) } // mutation { setComplete(id: 1, completedByPersonId: 5) { id completed completedOn } } ``` -------------------------------- ### Create DI-based Graph Type Source: https://github.com/shane32/graphql.di/blob/master/README.md This C# example shows how to create a GraphQL mutation type using DIObjectGraphBase, injecting an IRepository service into the constructor for use in field resolvers. ```csharp public class TodoMutation : DIObjectGraphBase { private readonly IRepository _repository; public TodoMutation(IRepository repository) { _repository = repository; } public async Task AddAsync(string title, string? notes) { var todo = new Todo { Title = title, Notes = notes, }; return await _repository.InsertAsync(todo, RequestAborted); } } ``` -------------------------------- ### Define Schema with Root DI Graph Types in C# Source: https://github.com/shane32/graphql.di/blob/master/README.md Illustrates how to define a GraphQL schema that inherits from 'Schema' and injects root DI graph types like QueryType and DIObjectGraphType. This setup is necessary for a functional GraphQL schema with dependency injection. ```csharp public class TodoSchema : Schema { public TodoSchema( IServiceProvider serviceProvider, QueryType queryType, // sample where QueryType inherits DIObjectGraphType DIObjectGraphType mutationType) // sample where Mutation inherits DIObjectGraphBase : base(serviceProvider) { Query = queryType; Mutation = mutationType; } } ``` -------------------------------- ### Configure GraphQL.NET with DI Source: https://github.com/shane32/graphql.di/blob/master/README.md This C# code snippet demonstrates how to register GraphQL.NET services and enable dependency injection support by calling .AddDI() during service configuration. ```csharp services.AddGraphQL(b => b .AddSystemTextJson() .AddSchema() .AddDI() .AddGraphTypes() .AddClrTypeMappings() .AddExecutionStrategy(OperationType.Query) ); ``` -------------------------------- ### Configure GraphQL Services with DI in .NET Source: https://context7.com/shane32/graphql.di/llms.txt This C# code snippet demonstrates how to configure GraphQL services in your .NET application's Program.cs or Startup.cs file. It includes registering the GraphQL.DI extension, necessary GraphQL.NET types, and essential services like DbContext and DataLoader with appropriate lifetimes. ```csharp // Program.cs or Startup.cs public void ConfigureServices(IServiceCollection services) { services.AddGraphQL(b => b .AddSchema() .AddSystemTextJson() .AddDI() // Register GraphQL.DI types .AddGraphTypes() // Register GraphQL.NET types .AddClrTypeMappings() // Enable automatic CLR type mappings .AddExecutionStrategy(OperationType.Query) // Required for scoped services ); // Register your services services.AddScoped(); services.AddScoped(); } ``` -------------------------------- ### Register GraphQL.DI with DI Container in C# Source: https://github.com/shane32/graphql.di/blob/master/README.md Shows how to configure the dependency injection container to use GraphQL.NET and GraphQL.DI. It includes adding system text JSON, the schema, DI integration, graph types, CLR type mappings, and specifying an execution strategy. ```csharp services.AddGraphQL(b => b .AddSystemTextJson() .AddSchema() .AddDI() // Register and configure GraphQL.DI types defined within the assembly .AddGraphTypes() // Register GraphQL.NET types defined within the assembly .AddClrTypeMappings() // Enable automatic CLR type mappings .AddExecutionStrategy(OperationType.Query) // Specify serial execution strategy ); ``` -------------------------------- ### Configure GraphQL Builder with AddDI() Extension Source: https://context7.com/shane32/graphql.di/llms.txt Configures GraphQL.NET services using extension methods for builder configuration. The AddDI() method is recommended for full integration. ```csharp // Full configuration using AddDI() - recommended services.AddGraphQL(b => b .AddSchema() .AddDI() // Registers all DI graph types and mappings .AddGraphTypes() .AddClrTypeMappings() ); // Granular configuration - use individual methods if needed services.AddGraphQL(b => b .AddSchema() .AddDIGraphTypes() // Register DIObjectGraphType<> generic types .AddDIGraphBases() // Register DIObjectGraphBase implementations as transients .AddDIClrTypeMappings() // Register CLR type mappings for DI graph types .AddGraphTypes() ); // Configure from specific assembly services.AddGraphQL(b => b .AddSchema() .AddDI(typeof(Query).Assembly) // Scan specific assembly for DI types .AddGraphTypes() ); ``` -------------------------------- ### Implement Root Query Type with Filtering in C# Source: https://github.com/shane32/graphql.di/blob/master/README.md Demonstrates creating a root query type that inherits from DIObjectGraphType. It shows how to define resolvers, handle multiple optional parameters for filtering, and use CancellationToken directly. Dependencies include IRepository and DIObjectGraphBase. ```csharp public class QueryType : DIObjectGraphType { public QueryType() { // Traditional code-first resolvers can be defined here // All resolvers defined in the Query type below are added to these definitions } } public class Query : DIObjectGraphBase { private readonly IRepository _repository; public Query(IRepository repository) { _repository = repository; } // Multiple optional parameters for filtering public async Task> TodosAsync( int? id, IEnumerable? ids, int? completedByPersonId, CancellationToken cancellationToken) // Can use CancellationToken directly (equivalent to the RequestAborted property) { IQueryable query = _repository.Todos; if (id.HasValue) query = query.Where(x => x.Id == id); if (ids != null) query = query.Where(x => ids.Contains(x.Id)); if (completedByPersonId != null) query = query.Where(x => x.CompletedByPersonId == completedByPersonId); return await query.ToListAsync(cancellationToken); } // Single item query public async Task TodoAsync(int id, CancellationToken cancellationToken) { return await _repository.Todos .Where(x => x.Id == id) .SingleOrDefaultAsync(cancellationToken); } } ``` -------------------------------- ### Access Source Object in Resolvers Source: https://context7.com/shane32/graphql.di/llms.txt Demonstrates multiple patterns for accessing the source object within GraphQL resolvers, including parameter naming, context, attributes, and properties. ```csharp public class TodoResolver : DIObjectGraphBase { // Pattern 1: Parameter named "source" with correct type public static int Id(Todo source) => source.Id; // Pattern 2: Via IResolveFieldContext parameter public static int Id(IResolveFieldContext context) => ((Todo)context.Source!).Id; // Pattern 3: Using [FromSource] attribute public static int Id([FromSource] Todo obj) => obj.Id; // Pattern 4: Using Source property (instance method) public int Id() => Source.Id; // Pattern 5: Using Context property (instance method) public int Id() => ((Todo)Context.Source!).Id; } // For simple property access, use static methods for better performance // Instance methods are needed when accessing injected services ``` -------------------------------- ### Create Subgraphs with [DIGraph] Attribute in C# Source: https://github.com/shane32/graphql.di/blob/master/README.md Demonstrates how to use the [DIGraph] attribute to easily create subgraphs, commonly used within mutations. It shows setting the graph type and returning a non-null object. Dependencies include DIObjectGraphBase and IRepository. ```csharp public class Mutation : DIObjectGraphBase { [DIGraph(typeof(TodoMutation))] public static string Todo() => ""; // a non-null object must be returned } public class TodoMutation : DIObjectGraphBase { private readonly IRepository _repository; public TodoMutation(IRepository repository) { _repository = repository; } public async Task AddAsync(string title, string notes) { var todo = new Todo { Title = title, Notes = notes, }; return await _repository.AddTodoAsync(todo, RequestAborted); } } ``` -------------------------------- ### Query Type Implementation with DIObjectGraphBase Source: https://context7.com/shane32/graphql.di/llms.txt Illustrates how to create query resolvers using DIObjectGraphBase, supporting filtering with multiple optional parameters and dependency injection. It also shows how CancellationToken is automatically bound. ```csharp // Query graph type definition public class QueryType : DIObjectGraphType { } // Query resolver with DI public class Query : DIObjectGraphBase { private readonly TodoDbContext _db; public Query(TodoDbContext db) { _db = db; } // Query with multiple optional filter parameters public async Task> TodosAsync( int? id, IEnumerable? ids, int? completedByPersonId, CancellationToken cancellationToken) // CancellationToken parameter is automatically bound { IQueryable query = _db.Set(); if (id.HasValue) query = query.Where(x => x.Id == id); if (ids != null) query = query.Where(x => ids.Contains(x.Id)); if (completedByPersonId != null) query = query.Where(x => x.CompletedByPersonId == completedByPersonId); return await query.ToListAsync(cancellationToken); } // Single item query public async Task TodoAsync(int id, CancellationToken cancellationToken) { return await _db.Set() .Where(x => x.Id == id) .SingleOrDefaultAsync(cancellationToken); } } // GraphQL query examples: // query { todos { id title completed } } // query { todos(id: 1) { id title notes } } // query { todos(completedByPersonId: 5) { id title completedBy { name } } } // query { todo(id: 1) { id title notes completed completedOn } } ``` -------------------------------- ### DIObjectGraphBase Properties and Extension Methods Source: https://github.com/shane32/graphql.di/blob/master/README.md Demonstrates accessing context properties like Source, RequestAborted, UserContext, User, and Metrics within a DIObjectGraphBase class. It also shows how to use extension methods defined for IResolveFieldContext. ```csharp // resolver method public static User GetUser(int id) => this.GetById(id); // extension method, usable both within code-first resolvers or DI resolvers public static User GetById(this IResolveFieldContext context, int id) { var repository = context.RequestServices!.GetRequiredService>(); return repository.GetById(id); } ``` -------------------------------- ### Integrate DataLoader for Batched Data Fetching Source: https://context7.com/shane32/graphql.di/llms.txt Implements and uses GraphQL.NET's DataLoader pattern for efficient, batched data fetching. Requires DI registration for the DataLoader. ```csharp // DataLoader implementation public class PersonDataLoader : DataLoaderBase { private readonly TodoDbContext _db; public PersonDataLoader(TodoDbContext db) { _db = db; } protected override async Task FetchAsync( IEnumerable> list, CancellationToken cancellationToken) { var ids = list.Select(x => x.Key); var people = await _db.Set() .Where(x => ids.Contains(x.Id)) .ToDictionaryAsync(x => x.Id, cancellationToken); foreach (var value in list) { people.TryGetValue(value.Key, out var person); value.SetResult(person); } } } // Resolver using DataLoader public class TodoResolver : DIObjectGraphBase { private readonly PersonDataLoader _personDataLoader; public TodoResolver(PersonDataLoader personDataLoader) { _personDataLoader = personDataLoader; } // Returns IDataLoaderResult for batched loading public IDataLoaderResult? CompletedBy() { if (!Source.CompletedByPersonId.HasValue) return null; return _personDataLoader.LoadAsync(Source.CompletedByPersonId.Value); } } // Register DataLoader as scoped service services.AddScoped(); ``` -------------------------------- ### GraphQL.DI: Direct DIObjectGraphBase Usage (C#) Source: https://github.com/shane32/graphql.di/blob/master/README.md Illustrates Pattern 2 for GraphQL.DI, where DIObjectGraphBase is used directly without a separate graph type definition. This pattern allows for direct DI into resolvers and offers flexibility in how source objects are accessed, including static methods and property access. ```csharp public class TodoResolver : DIObjectGraphBase { private readonly IRepository _repository; public TodoResolver(IRepository repository) { _repository = repository; } // Properties can be resolved using static methods public static int Id(Todo source) => source.Id; public static string Title(Todo source) => source.Title; // Complex resolvers can use injected services public async Task CompletedBy() { return await _repository.GetPersonById(Source.CompletedByPersonId); } } ``` -------------------------------- ### DIObjectGraphType Wrapper for Resolver Classes Source: https://context7.com/shane32/graphql.di/llms.txt Demonstrates how DIObjectGraphType wraps a DIObjectGraphBase class for GraphQL integration. It automatically discovers public methods as field resolvers and allows for traditional code-first field definitions. ```csharp public class TodoType : DIObjectGraphType { public TodoType() { // Mix traditional code-first field definitions Field(x => x.Id); Field(x => x.Title); Field(x => x.Notes, nullable: true); // Methods from TodoResolver are automatically added as fields: // - completedBy: Person // - completed: Boolean // - completedOn: DateTime // - comments: [Comment] } } // Resolver implementation public class TodoResolver : DIObjectGraphBase { private readonly PersonDataLoader _personDataLoader; public TodoResolver(PersonDataLoader personDataLoader) { _personDataLoader = personDataLoader; } public static bool Completed(Todo source) => source.Completed; public static DateTime? CompletedOn(Todo source) => source.CompletionDate; // Using DataLoader for efficient batched loading public IDataLoaderResult? CompletedBy() { if (!Source.CompletedByPersonId.HasValue) return null; return _personDataLoader.LoadAsync(Source.CompletedByPersonId.Value); } } ``` -------------------------------- ### Organize GraphQL Mutations into Subgraphs with DIGraphAttribute Source: https://context7.com/shane32/graphql.di/llms.txt Illustrates how to use the `[DIGraph]` attribute in C# to create nested mutation subgraphs, improving the organization of complex mutation schemas. This allows for logical grouping of related mutations. ```csharp // Root mutation with subgraphs public class Mutation : DIObjectGraphBase { // DIGraph attribute sets the return type to DIObjectGraphType [DIGraph(typeof(TodoMutation))] public static string Todo() => ""; // Return non-null object (value ignored) [DIGraph(typeof(UserMutation))] public static string User() => ""; } // Subgraph for todo-related mutations public class TodoMutation : DIObjectGraphBase { private readonly IRepository _repository; public TodoMutation(IRepository repository) { _repository = repository; } public async Task AddAsync(string title, string? notes) { var todo = new Todo { Title = title, Notes = notes }; return await _repository.InsertAsync(todo, RequestAborted); } public async Task DeleteAsync(int id) { return await _repository.DeleteTodoAsync(id, RequestAborted); } } // GraphQL mutation with subgraph: // mutation { // todo { // add(title: "Task", notes: "Details") { id title } // } // } // mutation { todo { delete(id: 1) } } ``` -------------------------------- ### DIObjectGraphBase Resolver with Constructor Injection Source: https://context7.com/shane32/graphql.di/llms.txt This C# code defines a GraphQL field resolver class, `TodoResolver`, that inherits from `DIObjectGraphBase`. It showcases constructor injection for dependency injection of services like `IRepository` and demonstrates accessing the `Source` object and `RequestAborted` token within resolver methods. ```csharp // Resolver class with full DI support public class TodoResolver : DIObjectGraphBase { private readonly IRepository _repository; // Constructor injection - works with scoped services public TodoResolver(IRepository repository) { _repository = repository; } // Access Source property for the parent object being resolved public async Task CompletedBy() { if (!Source.CompletedByPersonId.HasValue) return null; return await _repository.GetPersonById(Source.CompletedByPersonId.Value); } // Static methods for simple property resolution (better performance) public static bool Completed(Todo source) => source.Completed; public static DateTime? CompletedOn(Todo source) => source.CompletionDate; // Access cancellation token via RequestAborted property public async Task> Comments() { return await _repository.GetCommentsForTodo(Source.Id, RequestAborted); } } // Available properties in DIObjectGraphBase: // - Context: IResolveFieldContext - raw field resolution context // - Source: TSource - parent object being resolved // - RequestAborted: CancellationToken - request cancellation token // - UserContext: IDictionary - custom user context // - User: ClaimsPrincipal? - authenticated user // - Metrics: Metrics - performance metrics ``` -------------------------------- ### GraphQL.DI: Separate Type and Resolver Classes (C#) Source: https://github.com/shane32/graphql.di/blob/master/README.md Demonstrates Pattern 1 for GraphQL.DI, where type definitions and field resolution logic are split into separate classes. This pattern uses DIObjectGraphType for type definitions and DIObjectGraphBase for field resolvers, allowing for dependency injection within resolvers. ```csharp // Type definition public class TodoType : DIObjectGraphType { public TodoType() { // Classic code-first resolvers are defined here Field(x => x.Id); Field(x => x.Title); // Additional field resolvers are automatically mapped from TodoResolver } } // Field resolver implementation public class TodoResolver : DIObjectGraphBase { private readonly IRepository _repository; public TodoResolver(IRepository repository) { _repository = repository; } public async Task CompletedBy() { return await _repository.GetPersonById(Source.CompletedByPersonId); } } // Can be used alongside traditional GraphQL.NET types public class PersonType : ObjectGraphType { public PersonType() { Field(x => x.Id); Field(x => x.Name); } } ``` -------------------------------- ### Enable Parallel Resolver Execution with Scoped Attribute Source: https://context7.com/shane32/graphql.di/llms.txt Explains the use of the `[Scoped]` attribute in C# to create a dedicated service scope for individual GraphQL resolvers. This feature facilitates parallel execution of resolvers without interference, enhancing performance. ```csharp public class TodoMutation : DIObjectGraphBase { private readonly IRepository _repository; public TodoMutation(IRepository repository) { _repository = repository; } // Each resolver creates its own service scope // Allows parallel execution without interference [Scoped] public async Task AddAsync(string title, string notes) { var todo = new Todo { Title = title, Notes = notes }; return await _repository.AddTodoAsync(todo, RequestAborted); } [Scoped] public async Task DeleteAsync(int id) { return await _repository.DeleteTodoAsync(id, RequestAborted); } } // Both mutations can execute simultaneously without sharing service instances: // mutation { // add: todo { add(title: "Task 1", notes: "Notes") { id } } // delete: todo { delete(id: 5) } // } ``` -------------------------------- ### Define GraphQL Schema with DI Source: https://context7.com/shane32/graphql.di/llms.txt Defines GraphQL schemas using DI graph types. Supports direct DIObjectGraphType or separate type classes for schema definition. ```csharp public class TodoSchema : Schema { public TodoSchema( IServiceProvider serviceProvider, QueryType queryType, MutationType mutationType) : base(serviceProvider) { Query = queryType; Mutation = mutationType; } } // Alternative: Use DIObjectGraphType directly without separate type class public class AlternativeSchema : Schema { public AlternativeSchema( IServiceProvider serviceProvider, DIObjectGraphType queryType, // Inferred from Query class DIObjectGraphType mutationType) : base(serviceProvider) { Query = queryType; Mutation = mutationType; } } ``` -------------------------------- ### Scoped Attribute for DI Mutations Source: https://github.com/shane32/graphql.di/blob/master/README.md Illustrates the use of the [Scoped] attribute in GraphQL.DI to ensure that mutations requiring scoped services create a dedicated service scope before execution. This is crucial for managing service lifetimes and preventing concurrency issues. ```csharp public class TodoMutation : DIObjectGraphBase { // note: within this class, the Source property would be typed as an object and would return "" private readonly IRepository _repository; public TodoMutation(IRepository repository) { _repository = repository; } [Scoped] public async Task AddAsync(string title, string notes) { var todo = new Todo { Title = title, Notes = notes, }; return await _repository.AddTodoAsync(todo, RequestAborted); } [Scoped] public async Task DeleteAsync(int id) { // etc } } ``` -------------------------------- ### Register DI Graph Type in Schema Source: https://github.com/shane32/graphql.di/blob/master/README.md This C# code illustrates how to add a new DI-based graph type (TodoMutation) to your GraphQL schema by defining a root field in a dedicated ObjectGraphType. ```csharp public class MutationType : ObjectGraphType { public MutationType() { Field>("todo") .Resolve(_ => ""); } } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.