Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 53 additions & 1 deletion readme.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
<!--
This file was generate by the CaptureSnippets.
Source File: \readme.source.md
To change this file edit the source file and then re-run the generation using either the dotnet global tool (https://github.com/SimonCropp/CaptureSnippets#githubmarkdownsnippets) or using the api (https://github.com/SimonCropp/CaptureSnippets#running-as-a-unit-test).
-->

# GraphQL.EntityFramework

Add [EntityFramework Core IQueryable](https://docs.microsoft.com/en-us/dotnet/api/microsoft.entityframeworkcore.dbset-1.system-linq-iqueryable-provider) support to [GraphQL](https://github.com/graphql-dotnet/graphql-dotnet)
Expand Down Expand Up @@ -466,10 +472,14 @@ public class GraphQlControllerTests
{
static HttpClient client;

static WebSocketClient websocketClient;

static GraphQlControllerTests()
{
var server = GetTestServer();
client = server.CreateClient();
websocketClient = server.CreateWebSocketClient();
websocketClient.ConfigureRequest = request => { request.Headers["Sec-WebSocket-Protocol"] = "graphql-ws"; };
}

[Fact]
Expand Down Expand Up @@ -610,6 +620,48 @@ query ($id: String!)
response.EnsureSuccessStatusCode();
}

[Fact]
public Task Should_subscribe_to_companies()
{
var resetEvent = new AutoResetEvent(false);

var result = new GraphQLHttpSubscriptionResult(
new Uri("http://example.com/graphql"),
new GraphQLRequest
{
Query = @"
subscription {
companyChanged {
id
}
}"
},
websocketClient);

result.OnReceive += res =>
{
if (res != null)
{
Assert.Null(res.Errors);

if (res.Data != null)
{
resetEvent.Set();
}
}
};

var taskCancellationSource = new CancellationTokenSource();

var task = result.StartAsync(taskCancellationSource.Token);

Assert.True(resetEvent.WaitOne(TimeSpan.FromSeconds(10)));

taskCancellationSource.Cancel();

return task;
}

[Fact]
public async Task Post_null_query()
{
Expand All @@ -627,7 +679,7 @@ query ($id: String!)
}
}
```
<sup>[snippet source](/src/SampleWeb.Tests/GraphQlControllerTests.cs#L9-L176)</sup>
<sup>[snippet source](/src/SampleWeb.Tests/GraphQlControllerTests.cs#L13-L226)</sup>
<!-- endsnippet -->


Expand Down
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<LangVersion>latest</LangVersion>
<NoWarn>CS1591;NU5104</NoWarn>
<Version>1.9.2</Version>
<Version>1.10.0</Version>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<Copyright>Copyright $([System.DateTime]::UtcNow.ToString(yyyy)). All rights reserved</Copyright>
<PackageTags>EntityFrameworkCore, EntityFramework, GraphQL</PackageTags>
Expand Down
106 changes: 55 additions & 51 deletions src/GraphQL.EntityFramework/Where/ArgumentProcessor_List.cs
Original file line number Diff line number Diff line change
@@ -1,81 +1,85 @@
using System;
using System.Collections.Generic;
using System.Linq;
using GraphQL.EntityFramework;
using GraphQL.Types;

static partial class ArgumentProcessor
namespace GraphQL.EntityFramework
{
public static IEnumerable<TItem> ApplyGraphQlArguments<TItem, TSource>(this IEnumerable<TItem> items, ResolveFieldContext<TSource> context)
public static partial class ArgumentProcessor
{
return ApplyToAll(items, (type, x) => context.GetArgument(type, x));
}

static IEnumerable<TItem> ApplyToAll<TItem>(this IEnumerable<TItem> items, Func<Type, string, object> getArguments)
{
if (ArgumentReader.TryReadIds(getArguments, out var values))
public static IEnumerable<TItem> ApplyGraphQlArguments<TItem, TSource>(this IEnumerable<TItem> items, ResolveFieldContext<TSource> context)
{
var predicate = FuncBuilder<TItem>.BuildPredicate("Id", Comparison.In, values);
items = items.Where(predicate);
Guard.AgainstNull(nameof(items),items);
Guard.AgainstNull(nameof(context),context);
return ApplyToAll(items, (type, x) => context.GetArgument(type, x));
}

foreach (var where in ArgumentReader.ReadWhere(getArguments))
static IEnumerable<TItem> ApplyToAll<TItem>(this IEnumerable<TItem> items, Func<Type, string, object> getArguments)
{
var predicate = FuncBuilder<TItem>.BuildPredicate(where);
items = items.Where(predicate);
}

items = Order(items, getArguments);
if (ArgumentReader.TryReadIds(getArguments, out var values))
{
var predicate = FuncBuilder<TItem>.BuildPredicate("Id", Comparison.In, values);
items = items.Where(predicate);
}

if (ArgumentReader.TryReadSkip(getArguments, out var skip))
{
items = items.Skip(skip);
}
foreach (var where in ArgumentReader.ReadWhere(getArguments))
{
var predicate = FuncBuilder<TItem>.BuildPredicate(where);
items = items.Where(predicate);
}

if (ArgumentReader.TryReadTake(getArguments, out var take))
{
items = items.Take(take);
}
items = Order(items, getArguments);

return items;
}

static IEnumerable<TItem> Order<TItem>(IEnumerable<TItem> queryable, Func<Type, string, object> getArguments)
{
var items = queryable.ToList();
var orderBys = ArgumentReader.ReadOrderBy(getArguments).ToList();
IOrderedEnumerable<TItem> ordered;
if (orderBys.Count > 0)
{
var orderBy = orderBys.First();
var propertyFunc = PropertyCache<TItem>.GetProperty(orderBy.Path).Func;
if (orderBy.Descending)
if (ArgumentReader.TryReadSkip(getArguments, out var skip))
{
ordered = items.OrderByDescending(propertyFunc);
items = items.Skip(skip);
}
else

if (ArgumentReader.TryReadTake(getArguments, out var take))
{
ordered = items.OrderBy(propertyFunc);
items = items.Take(take);
}
}
else
{

return items;
}

foreach (var orderBy in orderBys.Skip(1))
static IEnumerable<TItem> Order<TItem>(IEnumerable<TItem> queryable, Func<Type, string, object> getArguments)
{
var propertyFunc = PropertyCache<TItem>.GetProperty(orderBy.Path).Func;
if (orderBy.Descending)
var items = queryable.ToList();
var orderBys = ArgumentReader.ReadOrderBy(getArguments).ToList();
IOrderedEnumerable<TItem> ordered;
if (orderBys.Count > 0)
{
ordered = ordered.ThenByDescending(propertyFunc);
var orderBy = orderBys.First();
var propertyFunc = PropertyCache<TItem>.GetProperty(orderBy.Path).Func;
if (orderBy.Descending)
{
ordered = items.OrderByDescending(propertyFunc);
}
else
{
ordered = items.OrderBy(propertyFunc);
}
}
else
{
ordered = ordered.ThenBy(propertyFunc);
return items;
}

foreach (var orderBy in orderBys.Skip(1))
{
var propertyFunc = PropertyCache<TItem>.GetProperty(orderBy.Path).Func;
if (orderBy.Descending)
{
ordered = ordered.ThenByDescending(propertyFunc);
}
else
{
ordered = ordered.ThenBy(propertyFunc);
}
}
}

return ordered;
return ordered;
}
}
}
114 changes: 59 additions & 55 deletions src/GraphQL.EntityFramework/Where/ArgumentProcessor_Queryable.cs
Original file line number Diff line number Diff line change
@@ -1,85 +1,89 @@
using System;
using System.Linq;
using GraphQL.EntityFramework;
using GraphQL.Types;

static partial class ArgumentProcessor
namespace GraphQL.EntityFramework
{
public static IQueryable<TItem> ApplyGraphQlArguments<TItem, TSource>(this IQueryable<TItem> queryable, ResolveFieldContext<TSource> context)
public static partial class ArgumentProcessor
{
return ApplyToAll(queryable, (type, x) => context.GetArgument(type, x));
}

static IQueryable<TItem> ApplyToAll<TItem>(this IQueryable<TItem> queryable, Func<Type, string, object> getArguments)
{
if (ArgumentReader.TryReadIds(getArguments, out var values))
{
var predicate = ExpressionBuilder<TItem>.BuildPredicate("Id", Comparison.In, values);
queryable = queryable.Where(predicate);
}

if (ArgumentReader.TryReadId(getArguments, out var value))
public static IQueryable<TItem> ApplyGraphQlArguments<TItem, TSource>(this IQueryable<TItem> queryable, ResolveFieldContext<TSource> context)
{
var predicate = ExpressionBuilder<TItem>.BuildSinglePredicate("Id", Comparison.Equal, value);
queryable = queryable.Where(predicate);
Guard.AgainstNull(nameof(queryable),queryable);
Guard.AgainstNull(nameof(context),context);
return ApplyToAll(queryable, (type, x) => context.GetArgument(type, x));
}

foreach (var where in ArgumentReader.ReadWhere(getArguments))
static IQueryable<TItem> ApplyToAll<TItem>(this IQueryable<TItem> queryable, Func<Type, string, object> getArguments)
{
var predicate = ExpressionBuilder<TItem>.BuildPredicate(where);
queryable = queryable.Where(predicate);
}

queryable = Order(queryable, getArguments);
if (ArgumentReader.TryReadIds(getArguments, out var values))
{
var predicate = ExpressionBuilder<TItem>.BuildPredicate("Id", Comparison.In, values);
queryable = queryable.Where(predicate);
}

if (ArgumentReader.TryReadSkip(getArguments, out var skip))
{
queryable = queryable.Skip(skip);
}
if (ArgumentReader.TryReadId(getArguments, out var value))
{
var predicate = ExpressionBuilder<TItem>.BuildSinglePredicate("Id", Comparison.Equal, value);
queryable = queryable.Where(predicate);
}

if (ArgumentReader.TryReadTake(getArguments, out var take))
{
queryable = queryable.Take(take);
}
foreach (var where in ArgumentReader.ReadWhere(getArguments))
{
var predicate = ExpressionBuilder<TItem>.BuildPredicate(where);
queryable = queryable.Where(predicate);
}

return queryable;
}
queryable = Order(queryable, getArguments);

static IQueryable<TItem> Order<TItem>(IQueryable<TItem> queryable, Func<Type, string, object> getArguments)
{
var orderBys = ArgumentReader.ReadOrderBy(getArguments).ToList();
IOrderedQueryable<TItem> ordered;
if (orderBys.Count > 0)
{
var orderBy = orderBys.First();
var property = PropertyCache<TItem>.GetProperty(orderBy.Path).Lambda;
if (orderBy.Descending)
if (ArgumentReader.TryReadSkip(getArguments, out var skip))
{
ordered = queryable.OrderByDescending(property);
queryable = queryable.Skip(skip);
}
else

if (ArgumentReader.TryReadTake(getArguments, out var take))
{
ordered = queryable.OrderBy(property);
queryable = queryable.Take(take);
}
}
else
{

return queryable;
}

foreach (var orderBy in orderBys.Skip(1))
static IQueryable<TItem> Order<TItem>(IQueryable<TItem> queryable, Func<Type, string, object> getArguments)
{
var property = PropertyCache<TItem>.GetProperty(orderBy.Path).Lambda;
if (orderBy.Descending)
var orderBys = ArgumentReader.ReadOrderBy(getArguments).ToList();
IOrderedQueryable<TItem> ordered;
if (orderBys.Count > 0)
{
ordered = ordered.ThenByDescending(property);
var orderBy = orderBys.First();
var property = PropertyCache<TItem>.GetProperty(orderBy.Path).Lambda;
if (orderBy.Descending)
{
ordered = queryable.OrderByDescending(property);
}
else
{
ordered = queryable.OrderBy(property);
}
}
else
{
ordered = ordered.ThenBy(property);
return queryable;
}
}

return ordered;
foreach (var orderBy in orderBys.Skip(1))
{
var property = PropertyCache<TItem>.GetProperty(orderBy.Path).Lambda;
if (orderBy.Descending)
{
ordered = ordered.ThenByDescending(property);
}
else
{
ordered = ordered.ThenBy(property);
}
}

return ordered;
}
}
}
Loading