FieldType BuildNavigationField <TSource, TReturn>( string name, Func <ResolveEfFieldContext <TDbContext, TSource>, IEnumerable <TReturn> >?resolve, IEnumerable <string>?includeNames, Type listGraphType, IEnumerable <QueryArgument>?arguments, string?description) where TReturn : class { Guard.AgainstNullWhiteSpace(nameof(name), name); var fieldType = new FieldType { Name = name, Description = description, Type = listGraphType, Arguments = ArgumentAppender.GetQueryArguments(arguments), Metadata = IncludeAppender.GetIncludeMetadata(name, includeNames) }; if (resolve != null) { fieldType.Resolver = new AsyncFieldResolver <TSource, IEnumerable <TReturn> >( context => { var efFieldContext = BuildContext(context); var result = resolve(efFieldContext); result = result.ApplyGraphQlArguments(context); return(efFieldContext.Filters.ApplyFilter(result, context.UserContext)); }); } return(fieldType); }
ConnectionBuilder <FakeGraph, TSource> BuildListConnectionField <TSource, TReturn>( string name, Func <ResolveEfFieldContext <TDbContext, TSource>, IEnumerable <TReturn> > resolve, IEnumerable <string> includeName, int pageSize, Type graphType) where TReturn : class { if (string.IsNullOrWhiteSpace(name)) { throw new ArgumentNullException(nameof(name)); } if (resolve == null) { throw new ArgumentNullException(nameof(resolve)); } if (pageSize < 0) { throw new ArgumentOutOfRangeException(nameof(pageSize)); } //lookup the graph type if not explicitly specified graphType = graphType ?? GraphTypeFinder.FindGraphType <TReturn>(); //create a ConnectionBuilder<graphType, TSource> type by invoking the static Create method on the generic type var fieldType = GetFieldType <TSource>(name, graphType); //create a ConnectionBuilder<FakeGraph, TSource> which will be returned from this method var builder = ConnectionBuilder <FakeGraph, TSource> .Create(name); //set the page size builder.PageSize(pageSize); //using reflection, override the private field type property of the ConnectionBuilder<FakeGraph, TSource> to be the ConnectionBuilder<graphType, TSource> object SetField(builder, fieldType); //add the metadata for the tables to be included in the query to the ConnectionBuilder<graphType, TSource> object IncludeAppender.SetIncludeMetadata(builder.FieldType, name, includeName); //set the custom resolver builder.ResolveAsync(async context => { //run the specified resolve function var enumerable = resolve(BuildEfContextFromGraphQlContext(context)); //apply any query filters specified in the arguments enumerable = enumerable.ApplyGraphQlArguments(context); //apply the global filter on each individually enumerated item if (filters != null) { enumerable = await filters.ApplyFilter(enumerable, context.UserContext); } //pagination does NOT occur server-side at this point, as the query has already executed var page = enumerable.ToList(); //return the proper page of data return(ConnectionConverter.ApplyConnectionContext( page, context.First, context.After, context.Last, context.Before)); }); //return the field to be added to the graph return(builder); }
FieldType BuildNavigationField <TSource, TReturn>( string name, Func <ResolveFieldContext <TSource>, IEnumerable <TReturn> > resolve, IEnumerable <string> includeNames, Type listGraphType, IEnumerable <QueryArgument> arguments) where TReturn : class { Guard.AgainstNullWhiteSpace(nameof(name), name); Guard.AgainstNull(nameof(resolve), resolve); return(new FieldType { Name = name, Type = listGraphType, Arguments = ArgumentAppender.GetQueryArguments(arguments), Metadata = IncludeAppender.GetIncludeMetadata(name, includeNames), Resolver = new AsyncFieldResolver <TSource, IEnumerable <TReturn> >( async context => { var result = resolve(context); result = result.ApplyGraphQlArguments(context); return await filters.ApplyFilter(result, context.UserContext); }) }); }
FieldType BuildNavigationField <TSource, TReturn>( string name, Func <ResolveEfFieldContext <TDbContext, TSource>, IEnumerable <TReturn> > resolve, IEnumerable <string> includeNames, Type listGraphType, IEnumerable <QueryArgument> arguments) where TReturn : class { Guard.AgainstNullWhiteSpace(nameof(name), name); Guard.AgainstNull(nameof(resolve), resolve); //return the new field type return(new FieldType { Name = name, Type = listGraphType, //take the arguments manually specified, if any, and append the query arguments Arguments = ArgumentAppender.GetQueryArguments(arguments), //add the metadata for the tables to be included in the query Metadata = IncludeAppender.GetIncludeMetadata(name, includeNames), //specify a custom resolve function Resolver = new AsyncFieldResolver <TSource, IEnumerable <TReturn> >( context => { var efFieldContext = BuildContext(context); //run the specified resolve function var result = resolve(efFieldContext); //apply any query filters specified in the arguments result = result.ApplyGraphQlArguments(context); //apply the global filter on each individually enumerated item return efFieldContext.Filters.ApplyFilter(result, context.UserContext); }) }); }
public EfGraphQLService( IModel model, ResolveDbContext <TDbContext> resolveDbContext, ResolveFilters resolveFilters = null) { Guard.AgainstNull(nameof(model), model); Guard.AgainstNull(nameof(resolveDbContext), resolveDbContext); this.resolveFilters = resolveFilters; this.resolveDbContext = resolveDbContext; foreach (var entityType in model.GetEntityTypes()) { var primaryKey = entityType.FindPrimaryKey(); //This can happen for views if (primaryKey == null) { continue; } var names = primaryKey.Properties.Select(x => x.Name).ToList(); keyNames.Add(entityType.ClrType, names); } includeAppender = new IncludeAppender(NavigationReader.GetNavigationProperties(model)); }
FieldType BuildNavigationField <TSource, TReturn>( string name, Func <ResolveFieldContext <TSource>, TReturn> resolve, IEnumerable <string> includeNames, Type graphType, IEnumerable <QueryArgument> arguments) where TReturn : class { Guard.AgainstNullWhiteSpace(nameof(name), name); Guard.AgainstNull(nameof(resolve), resolve); graphType = GraphTypeFinder.FindGraphType <TReturn>(graphType); return(new FieldType { Name = name, Type = graphType, Arguments = ArgumentAppender.GetQueryArguments(arguments), Metadata = IncludeAppender.GetIncludeMetadata(name, includeNames), Resolver = new AsyncFieldResolver <TSource, TReturn>(async context => { var result = resolve(context); if (await filters.ShouldInclude(context.UserContext, result)) { return result; } return null; }) }); }
FieldType BuildNavigationField <TSource, TReturn>( string name, Func <ResolveEfFieldContext <TDbContext, TSource>, TReturn> resolve, IEnumerable <string> includeNames, Type graphType) where TReturn : class { Guard.AgainstNullWhiteSpace(nameof(name), name); Guard.AgainstNull(nameof(resolve), resolve); //lookup the graph type if not explicitly specified graphType = graphType ?? GraphTypeFinder.FindGraphType <TReturn>(); //build field return(new FieldType { Name = name, Type = graphType, //add the metadata for the tables to be included in the query Metadata = IncludeAppender.GetIncludeMetadata(name, includeNames), //custom resolve function simply applies the global filters; typically it's a pass-through Resolver = new AsyncFieldResolver <TSource, TReturn>(async context => { var efFieldContext = BuildContext(context); //run resolve function var result = resolve(efFieldContext); //apply global filters and return null if necessary if (await efFieldContext.Filters.ShouldInclude(context.UserContext, result)) { return result; } return null; }) }); }
ConnectionBuilder <TGraph, TSource> BuildListConnectionField <TSource, TGraph, TReturn>( string name, Func <ResolveFieldContext <TSource>, IEnumerable <TReturn> > resolve, IEnumerable <string> includeName, int pageSize) where TGraph : ObjectGraphType <TReturn>, IGraphType where TReturn : class { Guard.AgainstNullWhiteSpace(nameof(name), name); Guard.AgainstNull(nameof(resolve), resolve); Guard.AgainstNegative(nameof(pageSize), pageSize); var builder = ConnectionBuilder.Create <TGraph, TSource>(); builder.PageSize(pageSize); builder.Name(name); IncludeAppender.SetIncludeMetadata(builder.FieldType, name, includeName); builder.Resolve(context => { var enumerable = resolve(context); enumerable = enumerable.ApplyGraphQlArguments(context); enumerable = enumerable.Where(item => GlobalFilters.ShouldInclude(context.UserContext, item)); var page = enumerable.ToList(); return(ConnectionConverter.ApplyConnectionContext( page, context.First, context.After, context.Last, context.Before)); }); return(builder); }
public void AddNavigationConnectionField <TSource, TReturn>( ComplexGraphType <TSource> graph, string name, Func <ResolveEfFieldContext <TDbContext, TSource>, IEnumerable <TReturn> >?resolve = null, Type?itemGraphType = null, IEnumerable <QueryArgument>?arguments = null, IEnumerable <string>?includeNames = null, int pageSize = 10, string?description = null) where TReturn : class { Guard.AgainstNull(nameof(graph), graph); Guard.AgainstNullWhiteSpace(nameof(name), name); Guard.AgainstNegative(nameof(pageSize), pageSize); itemGraphType ??= GraphTypeFinder.FindGraphType <TReturn>(); var fieldType = GetFieldType <TSource>(name, itemGraphType); var builder = ConnectionBuilder <TSource> .Create <FakeGraph>(name); if (description != null) { builder.Description(description); } builder.PageSize(pageSize).Bidirectional(); SetField(builder, fieldType); IncludeAppender.SetIncludeMetadata(builder.FieldType, name, includeNames); var hasId = keyNames.ContainsKey(typeof(TReturn)); if (resolve != null) { builder.ResolveAsync(async context => { var efFieldContext = BuildContext(context); var enumerable = resolve(efFieldContext); enumerable = enumerable.ApplyGraphQlArguments(hasId, context); enumerable = await efFieldContext.Filters.ApplyFilter(enumerable, context.UserContext); var page = enumerable.ToList(); return(ConnectionConverter.ApplyConnectionContext( page, context.First, context.After, context.Last, context.Before)); }); } var connection = builder; var field = graph.AddField(connection.FieldType); field.AddWhereArgument(hasId, arguments); }
ConnectionBuilder <FakeGraph, TSource> BuildListConnectionField <TSource, TReturn>( string name, Func <ResolveFieldContext <TSource>, IEnumerable <TReturn> > resolve, IEnumerable <string> includeName, int pageSize, Type graphType) where TReturn : class { Guard.AgainstNullWhiteSpace(nameof(name), name); Guard.AgainstNull(nameof(resolve), resolve); Guard.AgainstNegative(nameof(pageSize), pageSize); graphType = GraphTypeFinder.FindGraphType <TReturn>(graphType); var fieldType = GetFieldType <TSource>(name, graphType); var builder = ConnectionBuilder <FakeGraph, TSource> .Create(name); builder.PageSize(pageSize); SetField(builder, fieldType); IncludeAppender.SetIncludeMetadata(builder.FieldType, name, includeName); builder.ResolveAsync(async context => { var enumerable = resolve(context); enumerable = enumerable.ApplyGraphQlArguments(context); enumerable = await filters.ApplyFilter(enumerable, context.UserContext); var page = enumerable.ToList(); return(ConnectionConverter.ApplyConnectionContext( page, context.First, context.After, context.Last, context.Before)); }); return(builder); }
public EfGraphQLService(IModel model, GlobalFilters filters) { Guard.AgainstNull(nameof(model), model); this.filters = filters; foreach (var entityType in model.GetEntityTypes()) { var names = entityType.FindPrimaryKey().Properties.Select(x => x.Name).ToList(); keyNames.Add(entityType.ClrType, names); } includeAppender = new IncludeAppender(NavigationReader.GetNavigationProperties(model)); }
void AddEnumerableConnection <TSource, TGraph, TReturn>( ComplexGraphType <TSource> graph, string name, Func <ResolveEfFieldContext <TDbContext, TSource>, IEnumerable <TReturn> >?resolve, int pageSize, string?description, IEnumerable <QueryArgument>?arguments, IEnumerable <string>?includeNames) where TGraph : IGraphType where TReturn : class { var builder = ConnectionBuilder.Create <TGraph, TSource>(); builder.Name(name); if (description is not null) { builder.Description(description); } builder.PageSize(pageSize).Bidirectional(); IncludeAppender.SetIncludeMetadata(builder.FieldType, name, includeNames); var hasId = keyNames.ContainsKey(typeof(TReturn)); if (resolve is not null) { builder.ResolveAsync(async context => { var efFieldContext = BuildContext(context); var enumerable = resolve(efFieldContext); enumerable = enumerable.ApplyGraphQlArguments(hasId, context); enumerable = await efFieldContext.Filters.ApplyFilter(enumerable, context.UserContext); var page = enumerable.ToList(); return(ConnectionConverter.ApplyConnectionContext( page, context.First, context.After, context.Last, context.Before)); }); } // TODO: works around https://github.com/graphql-dotnet/graphql-dotnet/pull/2581/ builder.FieldType.Type = typeof(NonNullGraphType <ConnectionType <TGraph, EdgeType <TGraph> > >); var field = graph.AddField(builder.FieldType); field.AddWhereArgument(hasId, arguments); }
public EfGraphQLService( IModel model, ResolveDbContext <TDbContext> resolveDbContext, ResolveFilters?resolveFilters = null) { Guard.AgainstNull(nameof(model), model); Guard.AgainstNull(nameof(resolveDbContext), resolveDbContext); this.resolveFilters = resolveFilters; this.resolveDbContext = resolveDbContext; keyNames = model.GetKeyNames(); includeAppender = new IncludeAppender(NavigationReader.GetNavigationProperties(model)); }
ConnectionBuilder <TSource> BuildListConnectionField <TSource, TReturn>( string name, Func <ResolveEfFieldContext <TDbContext, TSource>, IEnumerable <TReturn> >?resolve, IEnumerable <string>?includeName, int pageSize, Type?itemGraphType, string?description) where TReturn : class { Guard.AgainstNullWhiteSpace(nameof(name), name); Guard.AgainstNegative(nameof(pageSize), pageSize); itemGraphType ??= GraphTypeFinder.FindGraphType <TReturn>(); var fieldType = GetFieldType <TSource>(name, itemGraphType); var builder = ConnectionBuilder <TSource> .Create <FakeGraph>(name); if (description != null) { builder.Description(description); } builder.PageSize(pageSize); SetField(builder, fieldType); IncludeAppender.SetIncludeMetadata(builder.FieldType, name, includeName); if (resolve != null) { builder.ResolveAsync(async context => { var efFieldContext = BuildContext(context); var enumerable = resolve(efFieldContext); enumerable = enumerable.ApplyGraphQlArguments(context); enumerable = await efFieldContext.Filters.ApplyFilter(enumerable, context.UserContext); var page = enumerable.ToList(); return(ConnectionConverter.ApplyConnectionContext( page, context.First, context.After, context.Last, context.Before)); }); } return(builder); }
ConnectionBuilder <TSource> BuildListConnectionField <TSource, TReturn>( string name, Func <ResolveEfFieldContext <TDbContext, TSource>, IEnumerable <TReturn> > resolve, IEnumerable <string>?includeName, int pageSize, Type?graphType) where TReturn : class { Guard.AgainstNullWhiteSpace(nameof(name), name); Guard.AgainstNull(nameof(resolve), resolve); Guard.AgainstNegative(nameof(pageSize), pageSize); //lookup the graph type if not explicitly specified graphType ??= GraphTypeFinder.FindGraphType <TReturn>(); //create a ConnectionBuilder<graphType, TSource> type by invoking the static Create<graphType> method on the generic type var builder = GetConnectionBuilder <TSource>(name, graphType); //set the page size builder.PageSize(pageSize); //add the metadata for the tables to be included in the query to the ConnectionBuilder<graphType, TSource> object IncludeAppender.SetIncludeMetadata(builder.FieldType, name, includeName); //set the custom resolver builder.ResolveAsync(async context => { var efFieldContext = BuildContext(context); //run the specified resolve function var enumerable = resolve(efFieldContext); //apply any query filters specified in the arguments enumerable = enumerable.ApplyGraphQlArguments(context); //apply the global filter on each individually enumerated item enumerable = await efFieldContext.Filters.ApplyFilter(enumerable, context.UserContext); //pagination does NOT occur server-side at this point, as the query has already executed var page = enumerable.ToList(); //return the proper page of data return(ConnectionConverter.ApplyConnectionContext( page, context.First, context.After, context.Last, context.Before)); }); //return the field to be added to the graph return(builder); }
public FieldType AddNavigationField <TSource, TReturn>( ComplexGraphType <TSource> graph, string name, Func <ResolveEfFieldContext <TDbContext, TSource>, TReturn?>?resolve = null, Type?graphType = null, IEnumerable <string>?includeNames = null, string?description = null) where TReturn : class { Guard.AgainstNull(nameof(graph), graph); Guard.AgainstNullWhiteSpace(nameof(name), name); graphType ??= GraphTypeFinder.FindGraphType <TReturn>(); FieldType field = new() { Name = name, Type = graphType, Description = description }; IncludeAppender.SetIncludeMetadata(field, name, includeNames); if (resolve != null) { field.Resolver = new AsyncFieldResolver <TSource, TReturn?>( async context => { var fieldContext = BuildContext(context); var result = resolve(fieldContext); if (await fieldContext.Filters.ShouldInclude(context.UserContext, result)) { return(result); } return(null); }); } return(graph.AddField(field)); } }
FieldType BuildNavigationField <TSource, TReturn>( string name, Func <ResolveEfFieldContext <TDbContext, TSource>, TReturn?>?resolve, IEnumerable <string>?includeNames, Type?graphType, string?description) where TReturn : class { Guard.AgainstNullWhiteSpace(nameof(name), name); graphType ??= GraphTypeFinder.FindGraphType <TReturn>(); var fieldType = new FieldType { Name = name, Type = graphType, Metadata = IncludeAppender.GetIncludeMetadata(name, includeNames), Description = description }; if (resolve != null) { fieldType.Resolver = new AsyncFieldResolver <TSource, TReturn?>( async context => { var efFieldContext = BuildContext(context); var result = resolve(efFieldContext); if (await efFieldContext.Filters.ShouldInclude(context.UserContext, result)) { return(result); } return(null); }); } return(fieldType); }
public FieldType AddNavigationListField <TSource, TReturn>( ComplexGraphType <TSource> graph, string name, Func <ResolveEfFieldContext <TDbContext, TSource>, IEnumerable <TReturn> >?resolve = null, Type?itemGraphType = null, IEnumerable <QueryArgument>?arguments = null, IEnumerable <string>?includeNames = null, string?description = null) where TReturn : class { Guard.AgainstNull(nameof(graph), graph); Guard.AgainstNullWhiteSpace(nameof(name), name); var hasId = keyNames.ContainsKey(typeof(TReturn)); FieldType field = new() { Name = name, Description = description, Type = MakeListGraphType <TReturn>(itemGraphType), Arguments = ArgumentAppender.GetQueryArguments(arguments, hasId, true), }; IncludeAppender.SetIncludeMetadata(field, name, includeNames); if (resolve != null) { field.Resolver = new AsyncFieldResolver <TSource, IEnumerable <TReturn> >( context => { var fieldContext = BuildContext(context); var result = resolve(fieldContext); result = result.ApplyGraphQlArguments(hasId, context); return(fieldContext.Filters.ApplyFilter(result, context.UserContext)); }); } return(graph.AddField(field)); }
public EfGraphQLService(IModel model, GlobalFilters filters, Func <object, TDbContext> dbContextFromUserContext) { if (model == null) { throw new ArgumentNullException(nameof(model)); } this.filters = filters; this.dbContextFromUserContext = dbContextFromUserContext ?? throw new ArgumentNullException(nameof(dbContextFromUserContext)); foreach (var entityType in model.GetEntityTypes()) { var primaryKey = entityType.FindPrimaryKey(); //This can happen for views if (primaryKey == null) { continue; } var names = primaryKey.Properties.Select(x => x.Name).ToList(); keyNames.Add(entityType.ClrType, names); } includeAppender = new IncludeAppender(NavigationReader.GetNavigationProperties(model)); }
public EfGraphQLService(IModel model, GlobalFilters filters) { Guard.AgainstNull(nameof(model), model); this.filters = filters; includeAppender = new IncludeAppender(NavigationReader.GetNavigationProperties(model)); }
public EntityGraphAdapter(EdmModel model, GlobalFilters filters) { // Guard.AgainstNull(nameof(model), model); this.filters = filters; includeAppender = new IncludeAppender(NavigationReader.GetNavigationProperties(model)); }
public EfGraphQLService(DbContext dbContext) { Guard.AgainstNull(nameof(dbContext), dbContext); includeAppender = new IncludeAppender(NavigationReader.GetNavigationProperties(dbContext)); }
public EfGraphQLService(Dictionary <Type, List <Navigation> > navigations) { Guard.AgainstNull(nameof(navigations), navigations); includeAppender = new IncludeAppender(navigations); }