Skip to content

Instantly share code, notes, and snippets.

@samyonr
Last active December 11, 2024 14:50
Show Gist options
  • Save samyonr/6bd85fad243bc39ab792d8788effc101 to your computer and use it in GitHub Desktop.
Save samyonr/6bd85fad243bc39ab792d8788effc101 to your computer and use it in GitHub Desktop.
EntityGraphQL IsAny not working for nullable array of ints
using Microsoft.EntityFrameworkCore;
namespace Entities;
public class DemoContext(DbContextOptions<DemoContext> options) : DbContext(options)
{
public DbSet<Property> Properties { get; set; }
public DbSet<PropertyType> PropertyTypes { get; set; }
public DbSet<Location> Locations { get; set; }
}
public class Property {
public required uint Id { get; set; }
public string? Name { get; set; }
public int? NullableInt { get; set; }
public int NonNullableInt { get; set; }
public int? TypeId { get; set; }
public PropertyType? Type { get; set; }
public Location? Location { get; set; }
}
public class PropertyType {
public required uint Id { get; set; }
public string? Name { get; set; }
public decimal? Premium { get; set; }
}
public class Location {
public required uint Id { get; set; }
public string? Name { get; set; }
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0" />
</ItemGroup>
</Project>
Microsoft Visual Studio Solution File, Format Version 12.00
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Server", "Server\Server.csproj", "{FAA97303-0DD9-4E4E-A866-C714D6AEF780}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{21869DD9-C881-4009-A039-907719C8D974}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Entities", "Entities\Entities.csproj", "{A035B7E1-BF3E-4EF1-8003-CCCAC3865490}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FAA97303-0DD9-4E4E-A866-C714D6AEF780}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FAA97303-0DD9-4E4E-A866-C714D6AEF780}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FAA97303-0DD9-4E4E-A866-C714D6AEF780}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FAA97303-0DD9-4E4E-A866-C714D6AEF780}.Release|Any CPU.Build.0 = Release|Any CPU
{21869DD9-C881-4009-A039-907719C8D974}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{21869DD9-C881-4009-A039-907719C8D974}.Debug|Any CPU.Build.0 = Debug|Any CPU
{21869DD9-C881-4009-A039-907719C8D974}.Release|Any CPU.ActiveCfg = Release|Any CPU
{21869DD9-C881-4009-A039-907719C8D974}.Release|Any CPU.Build.0 = Release|Any CPU
{A035B7E1-BF3E-4EF1-8003-CCCAC3865490}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A035B7E1-BF3E-4EF1-8003-CCCAC3865490}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A035B7E1-BF3E-4EF1-8003-CCCAC3865490}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A035B7E1-BF3E-4EF1-8003-CCCAC3865490}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
}
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*"
}
using Entities;
using EntityGraphQL.AspNet;
using EntityGraphQL.Schema.FieldExtensions;
namespace Server;
public static class Configuration
{
public static void ConfigureSchema(AddGraphQLOptions<DemoContext> options)
{
options.ConfigureSchema = schema =>
{
schema.UpdateQuery(queryType =>
queryType.ReplaceField(
"properties",
ctx => ctx.Properties,
"Return a list of properties. Optional filtered"
)
.UseFilter()
);
};
}
}
using Entities;
using EntityGraphQL.AspNet;
using Microsoft.EntityFrameworkCore;
using Server;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddDbContext<DemoContext>(opt => opt.UseInMemoryDatabase("test"));
builder.Services.AddGraphQLSchema<DemoContext>(Configuration.ConfigureSchema);
var app = builder.Build();
app.MapGraphQL<DemoContext>();
app.UseHttpsRedirection();
await app.RunAsync();
public partial class Program;
{
"$schema": "http://json.schemastore.org/launchsettings.json",
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:10875",
"sslPort": 44386
}
},
"profiles": {
"http": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": false,
"launchUrl": "swagger",
"applicationUrl": "http://localhost:5277",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"https": {
"commandName": "Project",
"dotnetRunMessages": true,
"launchBrowser": true,
"launchUrl": "swagger",
"applicationUrl": "https://localhost:7081;http://localhost:5277",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"launchUrl": "swagger",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="EntityGraphQL.AspNet" Version="5.5.3" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="9.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Relational" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Entities\Entities.csproj" />
<!--<ProjectReference Include="..\..\EntityGraphQL\src\EntityGraphQL.AspNet\EntityGraphQL.AspNet.csproj" />-->
</ItemGroup>
</Project>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.2"/>
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="9.0.0"/>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="9.0.0"/>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.12.0"/>
<PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" Version="9.0.0"/>
<PackageReference Include="xunit" Version="2.9.2"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.2"/>
</ItemGroup>
<ItemGroup>
<Using Include="Xunit"/>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Entities\Entities.csproj"/>
<ProjectReference Include="..\Server\Server.csproj"/>
</ItemGroup>
</Project>
using System.Net.Http.Json;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc.Testing;
namespace Tests;
public class CustomWebApplicationFactory : WebApplicationFactory<Program>
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
builder.UseEnvironment("Test");
}
}
public class UnitTest1(CustomWebApplicationFactory factory) : IClassFixture<CustomWebApplicationFactory>
{
[Fact]
public async Task TestString()
{
// Arrange
var client = factory.CreateClient();
const string query = """
query Properties {
properties(filter: "name.isAny([\"alice\", \"bob\"])") {
id
name
nullableInt
nonNullableInt
typeId
type {
id
name
premium
}
}
}
""";
// Act
using var response = await client.PostAsJsonAsync("/graphql", new { query });
// Assert
Assert.True(response.IsSuccessStatusCode);
var responseContent = await response.Content.ReadAsStringAsync();
Assert.Contains("data", responseContent);
Assert.Contains("properties", responseContent);
}
[Fact]
public async Task TestForeignKeyInt()
{
// Arrange
var client = factory.CreateClient();
const string query = """
query Properties {
properties(filter: "typeId.isAny([1, 2])") {
id
name
nullableInt
nonNullableInt
typeId
type {
id
name
premium
}
}
}
""";
// Act
using var response = await client.PostAsJsonAsync("/graphql", new { query });
// Assert
Assert.True(response.IsSuccessStatusCode);
var responseContent = await response.Content.ReadAsStringAsync();
Assert.Contains("data", responseContent);
Assert.Contains("properties", responseContent);
}
// Returns:
//"message": "Object of type 'System.Linq.Expressions.Expression1`1[System.Func`2[Entities.Property,System.Object]]' cannot be converted to type 'System.Linq.Expressions.Expression`1[System.Func`2[Entities.Property,System.Boolean]]'."
[Fact]
public async Task TestNullableInt()
{
// Arrange
var client = factory.CreateClient();
const string query = """
query Properties {
properties(filter: "nullableInt.isAny([1, 2])") {
id
name
nullableInt
nonNullableInt
typeId
type {
id
name
premium
}
}
}
""";
// Act
using var response = await client.PostAsJsonAsync("/graphql", new { query });
// Assert
Assert.True(response.IsSuccessStatusCode);
var responseContent = await response.Content.ReadAsStringAsync();
Assert.Contains("data", responseContent);
Assert.Contains("properties", responseContent);
}
[Fact]
public async Task TestNonNullableInt()
{
// Arrange
var client = factory.CreateClient();
const string query = """
query Properties {
properties(filter: "nonNullableInt.isAny([1, 2])") {
id
name
nullableInt
nonNullableInt
typeId
type {
id
name
premium
}
}
}
""";
// Act
using var response = await client.PostAsJsonAsync("/graphql", new { query });
// Assert
Assert.True(response.IsSuccessStatusCode);
var responseContent = await response.Content.ReadAsStringAsync();
Assert.Contains("data", responseContent);
Assert.Contains("properties", responseContent);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment