Question - Mutation for adding values to the system?
benhysell opened this issue · 3 comments
If one wanted to add a new User
from the test project, to the system would you do it via a mutation? Feels like I'm missing something fundamental and I'm not kicking anything up on Google.
Can one do:
schema.AddMutation("addUser",
new
{
name = string.Empty,
active = false
},
(db, args) => db.Users.AsQueryable(),
(db, args) =>
{
var newUser = new User()
{
Name = args.name,
Active = args.active
};
db.Users.Add(newUser);
db.SaveChanges();
}
);
var gql = CreateDefaultContext();
var results = gql.ExecuteQuery("mutation { addUser(name:\"Bob\", active: true) { id } }");
Stack trace
System.ArgumentException : Expression of type 'System.Linq.IQueryable`1[Tests.EF.EntityFrameworkMsSqlTests+User]' cannot be used for parameter of type 'Tests.EF.EntityFrameworkMsSqlTests+User'
at System.Linq.Expressions.Expression.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arg, ParameterInfo pi)
at System.Linq.Expressions.Expression.ValidateArgumentTypes(MethodBase method, ExpressionType nodeKind, ReadOnlyCollection`1& arguments)
at System.Linq.Expressions.Expression.Invoke(Expression expression, IEnumerable`1 arguments)
at GraphQL.Net.Executor`1.Execute(TContext context, GraphQLField field, ExecSelection`1 query) in C:\Jobs\graphql-net\GraphQL.Net\Executor.cs:line 70
at GraphQL.Net.Executor`1.Execute(GraphQLSchema`1 schema, GraphQLField field, ExecSelection`1 query) in C:\Jobs\graphql-net\GraphQL.Net\Executor.cs:line 17
at GraphQL.Net.GraphQL`1.ExecuteQuery(String queryStr) in C:\Jobs\graphql-net\GraphQL.Net\GraphQL.cs:line 44
at Tests.EF.EntityFrameworkMsSqlTests.SimpleMutationAddUser() in C:\Jobs\graphql-net\Tests.EF\EntityFrameworkMsSqlTests.cs:line 211
Hey Ben,
I can take a better look at this when I get home, however I suspect that the issue has to do with the type you're returning from the third argument (db, args) => db.Users.AsQueryable()
.
This argument is the query that is executed after a mutation executes. You're currently using the function that expects a single entity type (AddMutation
) instead of the function that expects a list type (AddListMutation
). Depending on what you want the results to return, you can do one of two things:
-
Change the function from
AddMutation
toAddListMutation
. This will return a list of all of your users after executing the mutation.or
-
Change the executing function to return a single user. That is, change
db.Users.AsQuerable()
todb.Users.LastOrDefault()
(or something similar). This will return the last user from the table.
This issue made me think about something that I hadn't considered before, which is that there's no way to pass info to the query returned from a mutation based on the results of the mutation. For example, this could be used if you wanted to execute a query that returned the exact user that was created after a mutation.
I would need to make some changes to mutation execution and add an overload in order to support this. Example syntax would look something like:
schema.AddMutation("addUser",
new
{
name = string.Empty,
active = false
},
(db, args) =>
{
var newUser = new User()
{
Name = args.name,
Active = args.active
};
db.Users.Add(newUser);
db.SaveChanges();
return newUser.Id; // return information from the mutation
},
// pass information to query as a third parameter
(db, args, id) => db.Users.FirstOrDefault(u => u.Id == id)
);
Note that in this example I've re-ordered the parameters to better represent their order of execution. I think this will be a likely breaking change in the next version.
My initial issue was the query itself, @ckimes89 you were correct. Cleaned that up, and ran as expected.
Thank you again for all of the help while I muddle through!