Instance per request for mutation class
See original GitHub issueCurrently for mutations, a single instance of the mutations class (e.g. PeopleMutations
) is created at startup. This differs ASP.NET Core controller classes, for which a new instance is created for each request. The instance-per-request approach allows dependency injection to be performed in the constructor, which is the preferred approach:
Prefer requesting dependencies as constructor parameters over resolving services from RequestServices. Requesting dependencies as constructor parameters yields classes that are easier to test.
Additionally, if several methods use the same DI parameters, the code for setting them up can be consolidated in the constructor, rather than having to be duplicated in each request method. EntityGraphQL mutations parallel controller methods and would benefit similarly, especially mutations that perform more than just database operations.
Relatedly, it’s worth noting that the DI conventions for controller methods and GraphQL mutations are currently reversed. For controller methods, DI services are annotated with FromServices and request data is not annotated. For GraphQL, DI services are not annotated and mutation arguments are annotated with MutationArguments
.
It would increase consistency and reduce the learning curve of EntityGraphQL if mutations followed the conventions as MVC controllers for instance-per-request and DI. It would also open the door to not requiring a separate args class for each mutation and instead allowing mutation fields to be specified as parameters, since all parameters not marked with FromServices
could be considered mutation fields.
Issue Analytics
- State:
- Created a year ago
- Reactions:1
- Comments:5 (2 by maintainers)
Thanks for the feedback.
FromServicesAttribute
however in ASP.NET 7 they are making that optional. I would seek to do the same and optionally support[FromServices]
[FromServices]
is not required for this, just need to look up what are services and what isn’tThanks for the feedback, this is great.
Hmm good point. I never thought of them as things like controllers until recently.
Previously they always had the lifetime of the schema which is generally a singleton. But could be what ever you register the schema as.
The new thing here is it now can inject services into the mutation constructor, which as you said if you register mutations as singletons and have services in the constructor then you hit the anti pattern.
Wasn’t an issue when you could only inject into the methods as that forced per request event though the object was not.
Good pickup. Makes sense to move towards always per request.
From: Edward Brey @.> Sent: Monday, July 4, 2022 11:14:06 PM To: EntityGraphQL/EntityGraphQL @.> Cc: Luke Murray @.>; State change @.> Subject: Re: [EntityGraphQL/EntityGraphQL] Instance per request for mutation class (Issue #126)
The 2.3.0 docs say:
When calling the mutuation it will ask the ServiceProvider for an instance of the class allowing for dependency injection at the constructor level, if that fails to return a result it will use Activator.CreateInstance.
Is that the right behavior? For ASP.NET Core controllers, I never thought of them as services themselves. For example, you don’t register them at startup. Instead, for each request, a controller instance is created and services are injected in. I would expect the same for the mutation objects (we can probably call them mutation controllers). They’d be created per request with ActivatorUtilities.CreateInstancehttps://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.activatorutilities.createinstance, rather accessed as services.
As with MVC controllers, defining mutation objects as services can be an anti-pattern, depending on the lifetime. If the service is registered as a singleton, you’d no longer have instance-per-request and wouldn’t be able to inject per-request services into the constructor. You’d also have multiple threads running on the same object when processing concurrent requests.
— Reply to this email directly, view it on GitHubhttps://github.com/EntityGraphQL/EntityGraphQL/issues/126#issuecomment-1173807698, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AABGHUMDKOLPP6B2WRZTNYDVSLPR5ANCNFSM5YNU2YZQ. You are receiving this because you modified the open/close state.Message ID: @.***>