Coder Social home page Coder Social logo

entitygraphql / entitygraphql Goto Github PK

View Code? Open in Web Editor NEW
381.0 381.0 51.0 7.62 MB

A GraphQL library for .NET

Home Page: https://entitygraphql.github.io/

License: MIT License

C# 99.58% ANTLR 0.11% HTML 0.08% Shell 0.01% JavaScript 0.23%
csharp dotnet graphql graphql-server

entitygraphql's Introduction

Entity GraphQL

A GraphQL library for .NET Core

Build

Head to entitygraphql.github.io for documentation and to get started.

EntityGraphQL is a .NET library that allows you to easily build a GraphQL API on top of your data model with the extensibility to easily bring multiple data sources together in the single GraphQL schema.

EntityGraphQL builds a GraphQL schema that maps to .NET objects. It provides the functionality to parse a GraphQL query document and execute that against your mapped objects. These objects can be an Entity Framework DbContext or any other .NET object, it doesn't matter.

A core feature of EntityGraphQL with Entity Framework (although EF is not a requirement) is that it builds selections of only the fields requested in the GraphQL query which means Entity Framework is not returning all columns from a table. This is done with the LINQ projection operator Select() hence it works across any object tree.

Please explore, give feedback or join the development.

Installation

The EntityGraphQL.AspNet Nuget package will get you easily set up with ASP.NET.

However the core EntityGraphQL Nuget package has no ASP.NET dependency.

Quick Start with Entity Framework

Note: There is no dependency on EF. Queries are compiled to IQueryable or IEnumberable linq expressions. EF is not a requirement - any ORM working with LinqProvider or an in-memory object will work - although EF well is tested.

1. Define your data context (in this example an EF context)

public class DemoContext : DbContext {
  public DbSet<Property> Properties { get; set; }
  public DbSet<PropertyType> PropertyTypes { get; set; }
  public DbSet<Location> Locations { get; set; }
}

public class Property {
  public uint Id { get; set; }
  public string Name { get; set; }
  public PropertyType Type { get; set; }
  public Location Location { get; set; }
}

public class PropertyType {
  public uint Id { get; set; }
  public string Name { get; set; }
  public decimal Premium { get; set; }
}

public class Location {
  public uint Id { get; set; }
  public string Name { get; set; }
}

2. Create a route

Here is an example for a ASP.NET. You will also need to install EntityGraphQL.AspNet to use MapGraphQL. You can also build you own endpoint, see docs.

Nuget

public class Startup {
  public void ConfigureServices(IServiceCollection services)
  {
      services.AddDbContext<DemoContext>(opt => opt.UseInMemoryDatabase());
      // This registers a SchemaProvider<DemoContext>
      services.AddGraphQLSchema<DemoContext>();
  }

  public void Configure(IApplicationBuilder app, DemoContext db)
  {
      app.UseRouting();
      app.UseEndpoints(endpoints =>
      {
          // default to /graphql endpoint
          endpoints.MapGraphQL<DemoContext>();
      });
  }
}

This sets up 1 end point:

  • POST at /graphql where the body of the post is a GraphQL query
  • You can authorize that route how you would any ASP.NET route. See Authorization below for details on having parts of the schema requiring Authorization/Claims

Note - As of version 1.1+ the EntityGraphQL.AspNet extension helper uses System.Text.Json. Previous versions used JSON.NET.

3. Build awesome applications

You can now make a request to your API. For example

  POST localhost:5000/graphql
  {
    properties { id name }
  }

Will return the following result.

{
  "data": {
    "properties": [
      {
        "id": 11,
        "name": "My Beach Pad"
      },
      {
        "id": 12,
        "name": "My Other Beach Pad"
      }
    ]
  }
}

Maybe you only want a specific property

  {
    property(id: 11) {
      id name
    }
  }

Will return the following result.

{
  "data": {
    "property": {
      "id": 11,
      "name": "My Beach Pad"
    }
  }
}

If you need a deeper graph or relations, just ask

  {
    properties {
      id
      name
      location {
        name
      }
      type {
        premium
      }
    }
  }

Will return the following result.

{
  "data": {
    "properties": [
      {
        "id": 11,
        "name": "My Beach Pad",
        "location": {
          "name": "Greece"
        },
        "type": {
          "premium": 1.2
        }
      },
      {
        "id": 12,
        "name": "My Other Beach Pad",
        "location": {
          "name": "Spain"
        },
        "type": {
          "premium": 1.25
        }
      }
    ]
  }
}

Visit documentation for more information.

Using expressions else where (EQL)

Lets say you have a screen in your application listing properties that can be configured per customer or user to only show exactly what they are interested in. Instead of having a bunch of checkboxes and complex radio buttons etc. you can allow a simple EQL statement to configure the results shown. Or use those UI components to build the query.

  // This might be a configured EQL statement for filtering the results. It has a context of Property
  (type.id = 2) or (type.id = 3) and type.name = "Farm"

This would compile to (Property p) => (p.Type.Id == 2 || p.Type.Id == 3) && p.Type.Name == "Farm";

This can then be used in various Linq functions either in memory or against an ORM.

// we create a schema provider to compile the statement against our Property type
var schemaProvider = SchemaBuilder.FromObject<Property>();
var compiledResult = EntityQueryCompiler.Compile(myConfigurationEqlStatement, schemaProvider);
// you get your list of Properties from you DB
var thingsToShow = myProperties.Where(compiledResult.LambdaExpression);

Another example is you want a customised calculated field. You can execute a compiled result passing in an instance of the context type.

// You'd take this from some configuration
var eql = @"if location.name = ""Mars"" then (cost + 5) * type.premium else (cost * type.premium) / 3"
var compiledResult = EntityQueryCompiler.Compile(eql, schemaProvider);
var theRealPrice = compiledResult.Execute<decimal>(myPropertyInstance);

Versioning

We do our best to follow Semantic Versioning:

Given a version number MAJOR.MINOR.PATCH, an increment in:

  • MAJOR version is when we make incompatible API changes,
  • MINOR version is when we add functionality in a backwards compatible manner, and
  • PATCH version is when we make backwards compatible bug fixes.

Contribute & Join the Development

Please do. Pull requests are very welcome. See the open issues for bugs or features that would be useful.

entitygraphql's People

Contributors

ahmedalejo avatar alex-birch avatar anderssonpeter avatar breyed avatar bzbetty avatar cyl1d3 avatar dependabot[bot] avatar elliotwannemacher-insource avatar gravllift avatar jtravis76 avatar leniency avatar lukemurray avatar mtetenkin avatar philippewaeber avatar pierrebelin avatar revazashvili avatar rjrudman avatar rubberchickenparadise avatar sammckoy avatar skjohansen avatar spoertm avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

entitygraphql's Issues

Resolving Queries on .NET Core 3.0 fails

I wanted to use this Library in my project, but couldn't test it in my project. So I've downloaded the sample one and done some investigation.
I found out that running the app on .NET Core 3.0 and trying to resolve some query is throwing the following logs:
System.NotSupportedException: The collection type 'EntityGraphQL.QueryVariables' on 'EntityGraphQL.QueryRequest.Variables' is not supported. at System.Text.Json.Serialization.JsonClassInfo.GetElementType(Type propertyType, Type parentType, MemberInfo memberInfo) at System.Text.Json.Serialization.JsonClassInfo.CreateProperty(Type declaredPropertyType, Type runtimePropertyType, PropertyInfo propertyInfo, Type parentClassType, JsonSerializerOptions options) at System.Text.Json.Serialization.JsonClassInfo.AddProperty(Type propertyType, PropertyInfo propertyInfo, Type classType, JsonSerializerOptions options) at System.Text.Json.Serialization.JsonClassInfo..ctor(Type type, JsonSerializerOptions options) at System.Text.Json.Serialization.JsonSerializerOptions.GetOrAddClass(Type classType) at System.Text.Json.Serialization.JsonSerializer.ReadAsync[TValue](Stream utf8Json, Type returnType, JsonSerializerOptions options, CancellationToken cancellationToken) at System.Threading.Tasks.ValueTask`1.get_Result() at Microsoft.AspNetCore.Mvc.Formatters.SystemTextJsonInputFormatter.ReadRequestBodyAsync(InputFormatterContext context, Encoding encoding) at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext) at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value) at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeFilterPipelineAsync>g__Awaited|19_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Logged|17_1(ResourceInvoker invoker) at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger) at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

Execute mutation without paramters?

I have a mutation without any parameters seems impossible to execute? (most likely its my GraphQL knowledge is lacking)

The following yields Missing bracets for mutation call scanForDevices.

mutation test {
  scanForDevices {
    id
  }
}

The following yields Error: line 2:17 extraneous input ')' expecting {1..11, 49}.

mutation test {
  scanForDevices() {
    id
  }
}

I have tried both with a empty parameter/arguments class and with no parameter/arguments class at all.

Method:

[GraphQLMutation]
public async Task<Expression<Func<DatabaseContext, IQueryable<Device>>>> ScanForDevices(DatabaseContext databaseContext, Empty parameters, IJobManager jobManager)
{
	var ids = await jobManager.StartWaitAsync<IEnumerable<int>, IDetectDeviceCommand>(ddc => ddc.ScanAsync()).ConfigureAwait(false);
	return ctx => ctx.Devices.Where(x => ids.Contains(x.Id));
}

ArgumentException in Case of Static Properties/Fields

Whenever there are static properties of fields inside DbContext class SchemaBuilder.FromObject throws an exception:

System.ArgumentException: 'Instance property 'ConnectionString' is not defined for type '###''

E. g. the EFDesigner likes to add a static ConnectionString property to each DbContext like this:

public static string ConnectionString { get; set; } = @"Name=ConfigModelConnectionString";

Would it make sense to just ignore all static properties and fields in the model class?
Or is there already a way that I missed to have it ignore those?

Thanks in advance for any idea on this
Andreas

How to filter using DateTime?

No docs! Where is docs?

Why the following not working?

query {
    auditLogs(type: 3) {
        oldValues newValues type affectedTableName affectedRecordKey 
        time
    }
}

Also how to paging? sorting? if not implemented using client side graphql, this lib wasted our time 2 weeks

Are asynchronous mutations supported?

I have the following method in a Mutation class:

[GraphQLMutation]
[GraphQLAuthorize(Roles.Admin)]
public async Task<Expression<Func<DatabaseContext, IQueryable<Device>>>> Scan(DatabaseContext databaseContext, Func<Task<IdentityUser>> getUser, IJobManager jobManager)
{
    var ids = await jobManager.StartWaitAsync<IEnumerable<int>, IDetectDeviceCommand>(ddc => ddc.ScanAsync()).ConfigureAwait(false);
    return ctx => ctx.Devices.Where(x => ids.Contains(x.Id));
}

But i get the error:

EntityGraphQL.Compiler.EntityGraphQLCompilerException: 'No mapped entity found for type 'System.Threading.Tasks.Task`1[System.Linq.Expressions.Expression`1[System.Func`2[MiFloraGateway.Database.DatabaseContext,System.Linq.IQueryable`1[MiFloraGateway.Database.Device]]]]''

Are there any plans for allowing async mutations?

Properties not showing up

I'm not exactly sure what I'm doing wrong, but following the example, when I make a query for properties, it will return an empty {} for every property I added to the DB, but it doesn't actually print the name or so in the {} that it returns for that object.

For example, if I had 3 propertyTypes in my DB, and I make this request
{ propertyTypes { id name premium } }

it would return
{ "errors": [], "data": { "propertyTypes": [ {}, {}, {} ] } }

As far as I can tell, from inspecting the code, the values are definitely present in the QueryResult object, but for some reason it seems to not serialize properly when returning out of the controller.

Introspection - build 0.20.1

Ok, Iโ€™m bit confused here. Been testing against your latest build 0.20.1 and notice a few things related to Introspection.

Missing INPUT_OBJECT kind:

In the BuildInputTypes method, there is a filter to get only IsInput. But I notice is set to true ONLY when using the AddInputType<>() method manually.
How is the auto-generated mutation setting this flag?

//SchemaIntrospection.cs
private static List<Models.TypeElement> BuildInputTypes(ISchemaProvider schema, IReadOnlyDictionary<Type, string> combinedMapping)
{
    var types = new List<Models.TypeElement>();

    foreach (ISchemaType schemaType in schema.GetNonContextTypes().Where(s => s.IsInput))
   {
       . . .
   }

//MappedSchemaProvider.cs
public SchemaType<TBaseType> AddInputType<TBaseType>(string name, string description)
{
    var tt = new SchemaType<TBaseType>(name, description, null, true);
     _types.Add(name, tt);
     return tt;
}

Duplicating Kind/Type object

The auto-generated mutation arguments has their kind/type repeating. The ofType is only need for LIST types. Doesn't seem to hurt anything, just bloat the JSON a bit.
Normal OBJECT types seem to be working as expected.
Fig1

Course if I comment out the IsInput filter that I mention above, it add INPUT_OBJECT types for ALL fields.

Example: the _Schema field was added twice.
For INPUT_OBJECT

  • fields should be empty array. Again, just bloat the JSON.
  • Cannot share the same name as an existing OBJECT types
  • TESTED: by changing the name to camelCase, worked for Introspection and Mutation queries

Fig2

Can't get it to work with playground/graphiql/altair

Can't get it to work with playground/graphiql/altair all of them complain that Mutation fields must be an object with field names as keys or a function which returns such an object., i have no mutations defined.

Is this a bug in this library or the others?

Filtering data on all columns

Is it possible to filter table data across all columns? In a example of your DemoContext:

{ movie(genre: 1) { id name genre } }

Thank you

Adding a operation inside entity

Lets say i have the following:

type RootQuery {
	"Return a Device by its Id"
	device(id: Int!): Device
	devices: [Device!]
}

type Device {
	id: Int!
        name: String
	logs: [LogEntry!]
}

type LogEntry {
	id: Int!
	when: Date!
        isError: Boolean!
	message: String
}

Is there some way to add a operation the Device type so that can get all logs that match a EQL expression filter? (i don't know if that is valid GraphQL or if its already supported by this package)

This would allow us to change the schema to:

type Device {
	id: Int!
        name: String
	logs: [LogEntry!]
        filteredLogs(filter: String!): [LogEntry!]
}

This would allow us to execute the following query to only get errors

devices {
  id,
  name,
  filteredLogs(filter: 'isError') {
    when,
    message
  }
}

Queries for Primary or Composite Keys

This is one of the nicest implementation in C# I've played with so far. Really Like how you already include the EF entities models. Other solutions want to re-add them. Felt like I was duplicating the work.

Do have a question when querying against primary or composite keys.

Not able to query when the primary key is not "id". Updated the schema from GroupId to Id and it worked perfectly.
{ group(groupid:1){ name } }

"message": "Error compiling query 'group(id:1)'. Field group not found"

This also goes for composite keys. GroupMembers have keys for username and groupid
{ groupmembers { username, email, groupid } }

"message": "Exception has been thrown by the target of an invocation."

It appears you are building a Lambda Expression, but not able to tell how you where calling EF.
Is this a Where() statement or using a Find() option against the keys?

BTW, been working on getting GraphiQl UI to work. Making some headway, building the schema model for the Document Explorer causing some heartburn,

Compile result doesn't contain Expression property.

Hi all,
in the example present in this documentation doesn't compile, because property Expression doesn't exists, instead LambdaExpression exists.

Could you verify the documentation ?

// we create a schema provider to compile the statement against our Property type
var schemaProvider = SchemaBuilder.FromObject();
var compiledResult = EqlCompiler.Compile(myConfigurationEqlStatement, schemaProvider);
// you get your list of Properties from you DB
var thingsToShow = myProperties.Where(compiledResult.Expression);

Thanks a lot.

GraphQL InputType argument parsing error & workaround

The following gives me what seems to be a parsing error:

Error: line 2:45 no viable alternative at input '['

mutation BrokenNestedInput {
  nestedArgumentQuery(dryRun: true, filters: [{field: itemId, equals: "1234"}]) {
    itemId
    itemName
  }
}

As far as I can tell, this happens any time I try to pass an input type within an input type, and a similar error occurs with '{' when I change filters to only accept a single element.

I discovered a workaround where I pass filters the following query variable:

## Query Variables
{
  "filter": 
  [
    {
      "field": "itemId", 
      "equals": "1234"
    }, 
    {
      "field": "itemId",
      "equals": "4321",
      "conjunction": "OR"
    }
  ]
}
----------
##"Query"
mutation NestedInputTypeTest($filter: [FilterInput]) {
  nestedArgumentQuery(filters: $filter) {
    itemId
    itemName
  }
}

This gives me the results I want with no parsing errors.

Also, just for clarification, I'm using mutation methods as makeshift queries to test a filtering system.

Return multiple entities from mutation?

Thanks for resolving #50 so fast!

But now i have a new issue.
I have the following mutation:

[GraphQLMutation]
public async Task<Expression<Func<DatabaseContext, IQueryable<Device>>>> ScanForDevices(Empty parameters, IJobManager jobManager)
{
	var ids = await jobManager.StartWaitAsync<IEnumerable<int>, IDetectDeviceCommand>(ddc => ddc.ScanAsync()).ConfigureAwait(false);
	return ctx => ctx.Devices.Where(x => ids.Contains(x.Id));
}

Where i try to return multiple Devices, but the schema only seems to indicate that i want to return 1.

{
  "name": "scanForDevices",
  "description": null,
  "args": [],
  "type": {
	"kind": "OBJECT",
	"name": "Device",
	"ofType": null
  },
  "isDeprecated": false,
  "deprecationReason": null
},

I guess my expected output is: (If this is valid GraphQL)

{
  "name": "scanForDevices",
  "description": null,
  "args": [],
  "type": {
	"kind": "LIST",
	"name": null,
	"ofType": {
	  "kind": "OBJECT",
	  "name": "Device",
	  "ofType": null
	}
  },
  "isDeprecated": false,
  "deprecationReason": null
},

Working with IFormFiles

Hello.
I have created some simple mutation for my app that is based on EntityGraphQL, and then I thought about sending files via this mutation. I've done some research about it and found this
https://github.com/jaydenseric/graphql-multipart-request-spec with some sample Middleware for doing this job but for competitive GraphQL Library.

I have tried to modify this Middleware to enable this feature to EntityGraphQL, but there comes the issue:

After insertion of IFormFile object to the Query Variables dictionary, then during the Query execution I'm getting the following error from QueryResult:
Object must implement IConvertible. and the mutation is not getting resolved.

Best way to rename field?

I have a property named IPAddress, and its converted to iPAddress what is the best way to rename it?

Currently i do the following:

schema.Type<Device>().RemoveField(x => x.IPAddress);
schema.Type<Device>().AddField("ipAddress", x => x.IPAddress, "");

The downside i have found is that i loose all comments that i have applied using the Description attribute. (Same thing happens with MACAddress)

See issue#16156

i want paging by Status, the query: {mydb( Take:100, Skip:1, Status:"dfgd" ) { id }}

the results:

{
"errors": [
{
"message": "See issue#16156"
}
],
"data": {}
}

which is the issue ?

__schema queries give no data?

If i run the following query

{
  __schema {
    types {
      name
    }
  }
}

I get the following response

{
  "errors": [],
  "data": {
    "__schema": {}
  }
}

If i run File.WriteAllText("schema.graphql", mappedSchemaProvider.GetGraphQLSchema()); the schema.graphql file contains a valid schema.

schema {
    query: RootQuery
    
}

scalar Int
scalar Float
scalar String
scalar Boolean
scalar ID



type RootQuery {
	"Collection of companies"
	companies: [Company!]
	"Pagination. [defaults: page = 1, pagesize = 10]"
	companyPager(page: Int!, pagesize: Int!): CompanyPagination

}

"Information about subscriptions"
type SubscriptionType {
	name: String
}

type Company {
	name: String
}

"Company Pagination"
type CompanyPagination {
	"total records to match search"
	total: Int!
	"total pages based on page size"
	pageCount: Int!
	"collection of companies"
	companies: [Company!]
}

Also if i try to run companyPager (basically the same code as in your demo) i can see that i get hits if i debug but none are returned..

query test {
  companyPager(page: 1, pagesize: 10) {
    companies {
      name
    }
    total
    pageCount
  }
}

Response:

{"errors":[],"data":{"companyPager":{}}}

The only difference i know is that I'm running .net core 3.1 and using a Postgres database.

introspection issue with latest GraphiQL

According to #17, support for the introspection has been added. I am running graphiql against my C# server. I can query my tables. However, the initial query passed when graphiql loads, gives an error. Seems to be a problem with 'fields.' Here is a smaller query which returns the same error:

{
  __type(name: "Application"){
    fields {
      name
    }
  }
}

And the error returned is

"Error compiling query 'fields'. Field 'fields' not found on current context '__Type'"

I am using a cloned version of master ( I had to downgrade some C# stuff because we use Framework 4.6.1, not Core). The 3rd newest commit on my repo is the merge for #17.

Integrate GraphiQL UI

GraphiQL would be a great addition to this project, and would help to provide a more well-rounded demo. It will also demonstrate several areas where the demo app has fallen out of sync with the evolving work being done on new functionality.

Pass an array in the query's argument

Hi,
I got this error message when trying to pass an array in the argument.
"Error: line 2:21 no viable alternative at input '['"

Example query:
{ tables (findIds: ["Id1", "Id2"]) { id, name } }

In the schema, I could see the information is generated correctly.
tables (findIds: [String]): ReturnType

In the customization, I put this code.
schemaProvider.AddField(tables, new { findIds = (string[]) null }, (db, p) => Process(db, p), "Some description", "ReturnType")

Is there something that I missed?

Thanks in advance.

P.S. I'm using ASP.Net Core 3.1 and EntityGraphQL 0.64.0

EQL syntax doesn't work

Hi all,
the EQL statement mentioned as an example, doesn't work, and the error is related to boolean condition.

(type.id = 2 or type.id = 3) and type.name == "Farm"

Could you please check the statement ?

Thanks a lot.

mutation expressions

According to the Readme, to have a full graph, we should return an Expression:

https://github.com/lukemurray/EntityGraphQL/issues

I have my mutation defined like this:

public Expression<Func<FlowAppContext, Item>> AddItem(FlowAppContext db, ItemInput newItem)
{
    var item = service.AddItem(newItem);
    service.Save();

    return ctx => ctx.Items.FirstOrDefault(i => i.id == item.id);
 }       

When I try to run the mutation though, an error comes back:

{
  "errors": [
    {
      "Message": "Object of type 'System.Linq.Expressions.Expression`1[System.Func`2[FlowApp.Models.FlowAppContext,FlowApp.Models.Item]]' cannot be converted to type 'FlowApp.Models.Item'."
    }
  ],
  "data": {}
}

I debugged it and found that in GraphQLMutationNode.cs on line 41, it does not pass the check to see if it is a LamdaExpression. The type, instead, is Expression so it tries to just return the results.

The demo looks to have the same signature structure as what I have above. Not sure what I am doing wrong. Would appreciate any help.

Error not bubble up

While leaping :) from v0.21.0 to 0.60.0, ran into this.

GraphiQL started throwing this error:
image

Even updated to 0.17.5 with same message.

Decided to remove the nuget package and reference the project directly. Then VS threw this message.
image

Added the custom scalar type and the Failed to fetch error when away.

schema.AddCustomScalarType(typeof(DateTime), "DateTime");
schema.AddCustomScalarType(typeof(DateTime?), "DateTime");

Not sure why it didn't bubble up into the QueryResult.

ServiceProvider - Mutation Introspection

For version 0.60.0
Found a strange critter roaming around in the introspection ServiceProvider.

{
    "name": "sendReport",
    "description": "Report sent via email",
    "args": [
        {
            "name": "serviceProvider",
            "description": null,
            "type": {
                "kind": "INPUT_OBJECT",
                "name": "iServiceProvider",
                "ofType": null
            },
            "defaultValue": null
        },
         ...
    ],
    "type": {
        "kind": "OBJECT",
        "name": "ResultDto",
        "ofType": null
    }
}
[GraphQLMutation("Report sent via email")]
public BusinessObjects.Dtos.ResultDto SendReport(DataContext context, IServiceProvider serviceProvider, BusinessObjects.Dtos.ReportDto report)

Quick work-around in SchemaIntrospection.cs solved the problem.

private static List<InputValue> BuildArgs(ISchemaProvider schema, CombinedMapping combinedMapping, IMethodType field)
{
    var args = new List<InputValue>();
    foreach (var arg in field.Arguments)
    {
        if (arg.Key.Equals("ServiceProvider", StringComparison.CurrentCultureIgnoreCase))
            continue;

Count selected objects by type?

Is there some way to after each query get a summary of how many of each .net type it contains (recursively and even if its just partial)?

Filtering with id doesn't work

Hi all,
the default schema generates a not plurar property (as mentioned in the example), but when It tries to filter result with id parameter I get this result:

message": "Constructor on type 'EntityGraphQL.Schema.RequiredField`1[[System.UInt32, System.Private.CoreLib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]' not found."
}

my query is:
{property(id : 1) { id name type location { id } }}

What's the problem?, after that the example is not updated (It seems).

Thanks a lot.

Custom queries are executed multiple times?

When running the demo project and running the following query

{
  actorPager(page: 1, pagesize: 10, search: "an")
  {
    people {
      firstName
    }
    total
    pageCount
  }
}

The QueryController.RunDataQuery method is executed once but the GraphQLSchema.PaginateActors is executed multiple times?

Mutation Func enums

I have 2 mutation methods and i have problem with calling it:

    [GraphQLMutation]
    public Expression<Func<CpiContext, Config>> AddConfig(AddConfigArgs args)
    {
        Func<CpiContext, Config> bodyFunction = db =>
        {
            CpiRepository repo = new CpiRepository(db);
            var result = repo.SaveConfigAsync(new Config()
            {
                Name = args.Name,
                Value = args.Value
            });
            result.Wait();
            return result.Result;
        };
        return db => bodyFunction(db);
    }

and

    [GraphQLMutation]
    public Expression<Func<CpiContext, Config>> GetEmptyInstance()
    {
        return db => new Config()
        {
        };
    }

When I browsed EntityGraphQL code, i found not implemented ExpressionType enums (ExpressionType.Invoke and ExpressionType.MemberInit) in method GraphQLMutationNode.ExecuteAsync(TContext context, GraphQLValidator validator, IServiceProvider serviceProvider).

Is it possible to add resolving for those enums? Thank you.

Error on EF Core 3 / 3.1

While constructing schema you need to remove type DbContextId in order to graphiql can work.
You can acomplish this with the following code:

demoSchema.RemoveTypeAndAllFields("DbContextId");

This just happens in EF Core 3.0 or above.

Running Mutation returns: "Unable to cast object of type 'EntityGraphQL.Compiler.GraphQLMutationNode' to type 'EntityGraphQL.Compiler.GraphQLQueryNode'."

Hi,

I am currently getting familiar with GraphQL in general - and used EntityGraphQL to get the hang of it and evaluate it for projects.
So this might not be an actual issue but me misunderstanding something fundamentally.

I followed the Readme for Mutations and implemented the

public class TestTableMutation
    {
        [GraphQLMutation("Add new TestTable Entry")]
        public Expression<Func<TestDbContext, TestTable>> AddTestTableViaMutation(TestDbContext context, TestTableArgs args)
        {
            TestTable newTable = new TestTable();
            newTable.Age = args.Age;
            newTable.Name = args.Name;
            newTable.Id = context.TestTable.Count();
            
            context.TestTable.Add(newTable);
            context.SaveChanges();
            
             return context => context.TestTable.First();
        }
    }

    [MutationArguments]
    public class TestTableArgs
    {
        public string Name;
        public int Age;
    }

Added the Mutation to the schema:

public void ConfigureServices(IServiceCollection services)
        {
            services.AddControllers().AddNewtonsoftJson();
            services.AddScoped<IInterProcessService, ServiceHandler>();
            services.AddDbContext<TestDbContext>();

            var schema = SchemaBuilder.FromObject<TestDbContext>(false,true);
            schema.AddMutationFrom(new TestTableMutation());
                    
            services.AddSingleton(schema);
        }

Yet when I run the query:

 {
     addTestTableViaMutation(name: "Stan", age:33)
 }

All I get is the following response:

{
    "errors": [
        {
            "message": "Unable to cast object of type 'EntityGraphQL.Compiler.GraphQLMutationNode' to type 'EntityGraphQL.Compiler.GraphQLQueryNode'."
        }
    ],
    "data": {}
}

tinkered with it for a couple days now and couldn't get it to run. Not sure what I am missing really.

Is there a change log?

Hi does this project have a change log?
I have the 0.50.0 version and just found out that 0.60.0 was released but i have no idea what it changed.

Async execution?

Hello. I want to ask if there is any way to execute the query asynchronously. Because it's working with EntityFrameworkCore and I wanna support async.

Authorization for types using the schema object

Currently, we can configure authorization for both fields and types using the [GraphQLAuthorize] attribute:
For types, we can set the [GraphQLAuthorize] attribute on the DbSet<> properties in our context class (if we're using EF of course):

[GraphQLAuthorize("super-admin")]
public DbSet<Purchase> Purchases{ get; set; }

For fields, we can set the [GraphQLAuthorize] attribute on the properties of our entity classes. Simple:

[GraphQLAuthorize("super-admin")]
public string Email { get; set; }

However, when it comes to configuring authorization using the schema object, it's currently only possible for fields:

schemaProvider.Type<User>().GetField("email").RequiresAllClaims("super-admin");

I can't do something like this, and I think it's reasonable to say it should be possible:

schemaProvider.Type<Purchase>().RequiresAllClaims("super-admin");

GraphQL Query string to LINQ Expression

Hi,

This library looks awesome. Apologies in advance if I've missed something here. I've spent some time looking through the examples on the front page but wasn't sure how to do this. What I'm looking for is a way to retrieve a LINQ Expression from a GraphQL string query. This would be totally decoupled from EF or even IQueryable.

The delegate would look exactly like this:

delegate Expression GetExpression(string graphQl);

Or potentially this with generics:

delegate Expression<Func<T, bool>> GetExpression<T>(string graphQl);

Is there a straight forward way to implement this delegate with this library?

Christian

how i filter by name?

hi, i try implement the example of the documentation, only works filter by id.

Query:
{
property(name: "daniel") {
name id
}
}

Results:
{
"errors": [
{
"message": "No argument 'name' found on field 'property'"
}
],
"data": {}
}

property contains:
public class Property
{
public uint Id { get; set; }
public string Name { get; set; }
public PropertyType Type { get; set; }
public Location Location { get; set; }
}

Accessing other services via mutations doesn't work

Hello,
I have encountered an issue while trying to access some service other service from my Mutation,
I'm passing my services as mutation args to the QueryObject method but it doesn't really matter because I'm getting the following StackTrace after execution of MakeSchema method:

Unhandled Exception: System.MissingMethodException: Cannot create an instance of an interface. at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean wrapExceptions, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor) at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean wrapExceptions, Boolean skipCheckThis, Boolean fillCache) at System.Activator.CreateInstance(Type type, Boolean nonPublic, Boolean wrapExceptions) at EntityGraphQL.Schema.MutationType..ctor(String methodName, ISchemaType returnType, Object mutationClassInstance, MethodInfo method, String description) at EntityGraphQL.Schema.MappedSchemaProvider`1.AddMutationFrom[TType](TType mutationClassInstance) at SportLeagueAPI.GraphQL.AppSchema.MakeSchema() in D:\SportLeagueAPI\GraphQL\AppSchema.cs:line 18 at SportLeagueAPI.Startup.ConfigureServices(IServiceCollection services) in D:\SportLeagueAPI\Startup.cs:line 75 --- End of stack trace from previous location where exception was thrown --- at Microsoft.AspNetCore.Hosting.ConventionBasedStartup.ConfigureServices(IServiceCollection services) at Microsoft.AspNetCore.Hosting.Internal.WebHost.EnsureApplicationServices() at Microsoft.AspNetCore.Hosting.Internal.WebHost.Initialize() at Microsoft.AspNetCore.Hosting.WebHostBuilder.Build() at SportLeagueAPI.Program.Main(String[] args) in D:\SportLeagueAPI\Program.cs:line 10

Separate GraphQLIgnore attribute into input and query

If you have an object that you share across a query object and as an input into a mutation you may want to label some as ignore from query and others ignore from the mutation input.

As an alternative right now, you can use simple DTOs for mutation inputs.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.