Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

F# Record and Purecode First schema Generation #2143

Closed
aammfe opened this issue Jul 15, 2020 · 25 comments
Closed

F# Record and Purecode First schema Generation #2143

aammfe opened this issue Jul 15, 2020 · 25 comments

Comments

@aammfe
Copy link

aammfe commented Jul 15, 2020

Describe the bug
While using F# Record in Purecode First schema Generation Hot throw following exception
HotChocolate.SchemaException: 'Unable to infer or resolve a schema type from the type reference Input: System.Collections.IEqualityComparer.'

image

To Reproduce
Steps to reproduce the behavior:

  1. F# code
    type Article = {ArticleId:string; Name:string }
  2. Repository
 public class BookService
        {
            private readonly IMongoCollection<Article> _articles;

            public BookService(IBookstoreDatabaseSettings settings)
            {
                var client = new MongoClient(settings.ConnectionString);
                var database = client.GetDatabase(settings.DatabaseName);

                _articles = database.GetCollection<Article>("Article");
            }

            public IQueryable<Article> GetArticles() => _articles.AsQueryable();
}
  1. Query
public class QueryType
        {
            private readonly BookService bookService;

            public QueryType(BookService bookService)
            {
                this.bookService = bookService;
            }

            [UseFiltering]
            public IQueryable<Article> GetArticles()
            {
                return bookService.GetArticles();
            }
        }
  1. Startup.cs
services.AddGraphQL(sp => SchemaBuilder.New()
              .AddQueryType<QueryType>()
              .Create());

Expected behavior
HotChoclate Should work with any .net type as it does with C#

@michaelstaib
Copy link
Member

We will have a look at it although it will take a while since at the moment we are focusing on the next major version of hot chocolate. If you want to try to implement this please go ahead.

@michaelstaib michaelstaib added this to the Backlog milestone Jul 20, 2020
@landy
Copy link

landy commented Jan 14, 2021

Hello, I would like to help with this but I'm really lost in the codebase and don't know where to start. Are there any pointers or something that would help me to try to implement this?

@michaelstaib
Copy link
Member

michaelstaib commented Jan 14, 2021

HI @landy,

we can help. Are you on our slack channel?

@timotheegloerfeld
Copy link

timotheegloerfeld commented Apr 9, 2021

For anyone tripping over this, it is possible to work around this by using [<ReferenceEquality>] on your records

@michaelstaib michaelstaib linked a pull request May 6, 2021 that will close this issue
3 tasks
@sep2 sep2 mentioned this issue May 10, 2021
3 tasks
@sep2
Copy link

sep2 commented May 10, 2021

For anyone tripping over this, it is possible to work around this by using [] on your records

@timotheegloerfeld Did you find a way to represent non-nullable type in F# record?

@sep2
Copy link

sep2 commented May 10, 2021

For anyone tripping over this, it is possible to work around this by using [] on your records

@timotheegloerfeld Did you find a way to represent non-nullable type in F# record?

Never mind, I found this [<GraphQLNonNullType>] attribute is exactly what I want.

@wonbyte
Copy link
Contributor

wonbyte commented May 20, 2021

For anyone tripping over this, it is possible to work around this by using [] on your records

@timotheegloerfeld I noticed that if my Record type contains an option then the equality error still occurs. Have you encountered this?

@timotheegloerfeld
Copy link

Yes I have encountered this too. Options don't seem to work as of now. Unfortunately I didn't have much time lately to investigate or setup unit tests as suggested in #2103

@wonbyte
Copy link
Contributor

wonbyte commented May 21, 2021

@landy I am beginning work on this if you want to help out!

@AlexeyRaga
Copy link
Contributor

@wonbyte Do you have a branch and/or a set of tasks that are to be done? Potentially my colleagues an I may be able to dedicate some time to it and help

@michaelstaib
Copy link
Member

@AlexeyRaga we did not get started on this so of you want to help just jump in. I can update the current sharp branch. What we need are test cases first. Essentially schema snapshot tests so that we see various sharp constructs to build a schema. Once we have the tests we can fix how things are inferred.

@AlexeyRaga
Copy link
Contributor

@michaelstaib sounds good! Can you point me to an example of such a test? I assume that you should have plenty of them for C#, so I can follow the same pattern?

@michaelstaib
Copy link
Member

In this case we are interested in schema snapshot tests, which are simple to write. Essentially we setup a new service collection and configure our GraphQL server, at the end we use the extension method BuildSchemaAsync to create a schema from our configuration. We are using snapshooter to create a SDL representation of the schema MatchSnapshot. Essentially if this test succeeds it creates a schema representation that can be reviewed and every new test run validates against this snapshot.

[Fact]
public async Task EnsureThatFieldsWithDifferentCasingAreNotMerged()
{
    await new ServiceCollection()
        .AddGraphQL()
        .AddQueryType<QueryFieldCasing>()
        .BuildSchemaAsync()
        .MatchSnapshotAsync();
}

@michaelstaib
Copy link
Member

I will update the F# branch and you can do a PR to the branch.

@AlexeyRaga
Copy link
Contributor

@michaelstaib awaiting for the branch to be rebased

@Ciantic
Copy link
Contributor

Ciantic commented Nov 17, 2021

I know this is not implemented yet, but I suspect I got a same problem, when trying to use CliMutable records, e.g.:

Unable to infer or resolve a schema type from the type reference Input: IEqualityComparer. (HotChocolate.Types.ObjectType<.Program.Person>)

Here is an easy repro:

With F#:

open System
open Microsoft.AspNetCore.Builder
open Microsoft.Extensions.Hosting
open Microsoft.Extensions.DependencyInjection
open Microsoft.EntityFrameworkCore 
open HotChocolate.Types 
open HotChocolate.Data
open HotChocolate;

[<CLIMutable>]
type Person =
    { Id : Guid
      FirstName : string
      LastName : string
      Address : string
      City : string}

type AppDbContext(opts) =
    inherit DbContext(opts)
    member this.Persons = this.Set<Person>()

type Query() =
    [<UsePaging>]
    [<UseProjection>]
    [<UseFiltering>]
    [<UseSorting>]
    member this.Persons ([<Service>] dbContext: AppDbContext) =
        dbContext.Persons

[<EntryPoint>]
let main args =

    let builder = WebApplication.CreateBuilder(args)

    builder.Services
            .AddDbContext<AppDbContext>(
                fun opts -> opts.UseSqlite("Data Source=foo.sqlite") |> ignore
            )
            .AddGraphQLServer()
            .AddQueryType<Query>()
            .AddFiltering()
            .AddSorting()
            .AddProjections() |> ignore

    let app = builder.Build()

    app.UseDeveloperExceptionPage() |> ignore
    app.UseRouting() |> ignore
    app.MapGraphQL() |> ignore

    let createDb =
        use scope = app.Services.CreateScope()
        let db = scope.ServiceProvider.GetRequiredService<AppDbContext>()
        db.Database.EnsureDeleted() |> Console.WriteLine
        db.Database.EnsureCreated() |> Console.WriteLine

    createDb
    
    app.Run()

    0 // Exit code
  <ItemGroup>
    <PackageReference Include="EntityFrameworkCore.FSharp" Version="6.0.2" />
    <PackageReference Include="HotChocolate.AspNetCore" Version="12.2.1" />
    <PackageReference Include="HotChocolate.Data" Version="12.3.0" />
    <PackageReference Include="HotChocolate.Data.EntityFramework" Version="12.3.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.0" />
  </ItemGroup>

@Junocaen

This comment was marked as duplicate.

@stale stale bot added the ⌛ stale Nothing happened with this issue in quite a while label May 4, 2022
@adelarsq
Copy link
Contributor

adelarsq commented May 4, 2022

I am interested on this. Send some love for F# :)

@stale stale bot removed the ⌛ stale Nothing happened with this issue in quite a while label May 4, 2022
@stale stale bot added the ⌛ stale Nothing happened with this issue in quite a while label Jul 3, 2022
@adelarsq
Copy link
Contributor

adelarsq commented Jul 4, 2022

It's there any work on this issue?

@stale stale bot removed the ⌛ stale Nothing happened with this issue in quite a while label Jul 4, 2022
@AlexeyRaga
Copy link
Contributor

Looks like there is none :(

@michaelstaib
Copy link
Member

@AlexeyRaga we need a couple of F# natives to help us. If there is interest join us on slack and lets get started.

https://slack.chillicream.com

@stale stale bot added the ⌛ stale Nothing happened with this issue in quite a while label Nov 4, 2022
@ChilliCream ChilliCream deleted a comment from stale bot Nov 5, 2022
@stale stale bot removed the ⌛ stale Nothing happened with this issue in quite a while label Nov 5, 2022
@ChilliCream ChilliCream deleted a comment from stale bot Nov 5, 2022
@ChilliCream ChilliCream deleted a comment from stale bot Nov 5, 2022
@AlexeyRaga
Copy link
Contributor

Looks like the work is being done here: #5595

@glen-84
Copy link
Collaborator

glen-84 commented Oct 20, 2023

@AlexeyRaga @michaelstaib Was this resolved by #5973?

@AlexeyRaga
Copy link
Contributor

@glen-84 Partially, yes.
We should be OK now for the equality stuff, and we should be able to use Option.

More work is required to make it a nice F# experience, though, for example:

  • Support F# union types (map to GraphQL Union or/and Interface)
  • Support for F# nullability: every field of an F# record should be treated as non-nullable by default, unless it is of type Option<T>

When these two are done, I'll call it a decent F# support :)

@glen-84
Copy link
Collaborator

glen-84 commented Oct 21, 2023

Thanks for the summary, though I'm asking more specifically about this particular issue – has the error in the OP been resolved? If so, I'll go ahead and close this issue. 🙂

@glen-84 glen-84 closed this as completed Nov 11, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.