如何在C#中获得GraphQl字段?

发布于 2025-01-23 12:27:01 字数 616 浏览 0 评论 0原文

我正在研究GraphQl-> SQL解析器包括一些连接,因此是否要求某个字段会产生性能差异。有没有办法找到这个问题?

我正在学习有关对象类型的知识,因此我认为这可能与在其上设置溶要有关。但是,一个解析器在独立于其他事物的领域级别上起作用。尽管我试图在最高查询级别上弄清楚哪个字段已在GraphQl查询中要求。这将塑造SQL查询。

public class QueryType : ObjectType<Query>
{
    protected override void Configure(IObjectTypeDescriptor<Query> descriptor)
    {
        descriptor
            .Field(f => f.GetACUMonthlySummary(default!, default!, default!, default!, default!, default!))
            .Type<ListType<ACUMonthlySummaryType>>();
    }
}

我看到了JS的相关问题,但没有在C#和Hotchocaly中找到任何示例,这是我们正在使用的。

I'm working on a GraphQL -> SQL parser that includes some joins, so it makes a performance difference whether a certain field is requested. Is there a way to find that out?

I'm learning about object types, so I think it might have something to do with setting a resolver on it. But a resolver works at the level of the field that's being requested independently of other things. Whereas I'm trying to figure out on the top-most Query level which fields have been requested in the GraphQL query. That will shape the SQL query.

public class QueryType : ObjectType<Query>
{
    protected override void Configure(IObjectTypeDescriptor<Query> descriptor)
    {
        descriptor
            .Field(f => f.GetACUMonthlySummary(default!, default!, default!, default!, default!, default!))
            .Type<ListType<ACUMonthlySummaryType>>();
    }
}

I saw related questions for js, but didn't find any examples specifically in C# and HotChocolate, which is what we're using.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

沫尐诺 2025-01-30 12:27:01

我不确定是否建议这样做,所以我感谢反馈,但是我找到了以下方法来列出所有选定的节点:

  1. 注入iresolvercontext上下文(使用hotchocaly.resolvers)作为参数之一询问。
  2. context.selection.syntaxnode.selectionset.selections给出iEnumerable&lt; iselectionNode&gt;。这完全包含用户选择的字段。

I'm not sure if this is recommended, so I appreciate feedback, but I found the following way to list all selected nodes:

  1. Inject IResolverContext context (using HotChocolate.Resolvers) as one of the parameters in the query.
  2. context.Selection.SyntaxNode.SelectionSet.Selections gives an IEnumerable<ISelectionNode>. That contains exactly the fields the user has selected.
〆凄凉。 2025-01-30 12:27:01

如果您使用的是基于注释的方法,只需在查询方法上添加iresolvercontext参数。

 public async Task<Form> GetForm(long id, string organisationId, [Service] IFormRepository formRepository,
    IResolverContext context)
{
    //context.Selection.SyntaxNode.SelectionSet.Selections
    var form = await formRepository.GetFormById(id, organisationId);
    return new Form
    {
        Id = form.Id,
        Name = form.Name,
        ShortUrl = form.ShortUrl,
        PublishStatus = form.PublishStatus,
        Description = form.Description,
        OrganisationId = form.OrganizationId
    };
}

通过使用context.selection.syntaxnode.selectionset.selections获取字段

Just add IResolverContext parameter on query method if you are using Annotation based approach.

 public async Task<Form> GetForm(long id, string organisationId, [Service] IFormRepository formRepository,
    IResolverContext context)
{
    //context.Selection.SyntaxNode.SelectionSet.Selections
    var form = await formRepository.GetFormById(id, organisationId);
    return new Form
    {
        Id = form.Id,
        Name = form.Name,
        ShortUrl = form.ShortUrl,
        PublishStatus = form.PublishStatus,
        Description = form.Description,
        OrganisationId = form.OrganizationId
    };
}

Get fields by using context.Selection.SyntaxNode.SelectionSet.Selections

美人如玉 2025-01-30 12:27:01

例如(一个简单的一个),您有一个名为“员工”的类,它具有firstNamelastName属性。您可能希望GraphQL端点能够为员工的fullname字段公开,该字段将在内部串联first和姓氏 。请注意,FirstName和LastName值作为员工数据库表的列存在,但FullName字段将被派发。

public class EmployeeType : ObjectType<Employee> {
    protected override void Configure(IObjectTypeDescriptor<Employee> descriptor) {
        descriptor.Field(@"FullName")
            .Type<StringType>()
            .ResolveWith<Resolvers>( p => p.GetFullName(default!, default!) )
            .UseDbContext<AppDbContext>()
            .Description(@"Full name of the employee");
    }

    private class Resolvers {
        
        public string GetFullName([Parent] Employee e, [ScopedService] AppDbContext context) {
            return e.FirstName + " " + e.LastName;
        }
    }
}

我很确定您必须使用ParentAttribute注释员工。

在分辨率文档中了解更多有关此内容的信息

Say for example(A simple one) you have a class called employee and it has FirstName and LastName properties. You may want want the GraphQL endpoint to expose a FullName field for the employee that will internally concatenate the first and last name. Note that FirstName and LastName values exist as columns of the Employee database table but the FullName field will be derived.

public class EmployeeType : ObjectType<Employee> {
    protected override void Configure(IObjectTypeDescriptor<Employee> descriptor) {
        descriptor.Field(@"FullName")
            .Type<StringType>()
            .ResolveWith<Resolvers>( p => p.GetFullName(default!, default!) )
            .UseDbContext<AppDbContext>()
            .Description(@"Full name of the employee");
    }

    private class Resolvers {
        
        public string GetFullName([Parent] Employee e, [ScopedService] AppDbContext context) {
            return e.FirstName + " " + e.LastName;
        }
    }
}

I'm pretty sure you'd have to annotate the Employee using the ParentAttribute.

Learn more about this in the resolver documentation

不气馁 2025-01-30 12:27:01

其他答案可以使一层降低以获取字段,但是当您想包括孩子的属性名称时,请勿工作。 IE:如果您的查询是

查询myquery {myquery(id:“ 123”){ID名称embeddeddoc {embeddedDocid embeddedDocName}}}}}}

如果要接收以下内容,
ID
姓名
嵌入DEDDOC
嵌入DOCID
嵌入DEDOCNAME

或在属性中传递的滤波器上,您可以使用以下扩展方法:

public static class HotChocolateExtensions
    {
    public static bool ContainsSelection(this IResolverContext resolverContext, PropertyInfo propertyInfo)
    {
        return resolverContext.ContainsSelection($"{propertyInfo.Name[..1].ToLower()}{propertyInfo.Name[1..]}");
    }
    public static bool ContainsSelection(this IResolverContext resolverContext, string selection)
    {
        return resolverContext.GetQuerySelections().Contains(selection);
    }
    public static IEnumerable<string> GetQuerySelections(this IResolverContext resolverContext)
    {
        var fields = resolverContext.Selection.SelectionSet?.Selections.Where(x => x.Kind == HotChocolate.Language.SyntaxKind.Field) ?? [];
        return fields.GetQuerySelections();
    }
    private static IEnumerable<string> GetQuerySelections(this IEnumerable<ISelectionNode> selectionNodes)
    {
        List<string> querySelections = new List<string>();
        foreach (var selectionNode in selectionNodes)
        {
            if (((dynamic)selectionNode).SelectionSet is not null)
            {
                querySelections.Add(selectionNode.ToString().Split(' ')[0]);
                IReadOnlyList<ISelectionNode>? subSelectionNodes = ((dynamic)selectionNode).SelectionSet?.Selections;
            
                querySelections.AddRange(GetQuerySelections(subSelectionNodes?.Where(x => x.Kind == HotChocolate.Language.SyntaxKind.Field) ?? []));
           }
            else
            {
                querySelections.Add(selectionNode.ToString());
            }
         }
         return querySelections;
     }
}

用法:

public bool FooQuery(IResolverContext resolverContext)
{
     return resolverContext.ContainsSelection(typeof(MyModel).GetProperty(nameof(MyModel.Id))!)
}

The other answers work to get one layer down to get the fields, but do not work when you want to include the property names of the children. IE: if your query is

query myQuery{ myQuery(id: "123"){ id name embeddedDoc{ embeddedDocId embeddedDocName } } }

If you want to receive the following:
id
name
embeddedDoc
embeddedDocId
embeddedDocName

OR filter on the passed in properties, you can use the following extension methods:

public static class HotChocolateExtensions
    {
    public static bool ContainsSelection(this IResolverContext resolverContext, PropertyInfo propertyInfo)
    {
        return resolverContext.ContainsSelection(
quot;{propertyInfo.Name[..1].ToLower()}{propertyInfo.Name[1..]}");
    }
    public static bool ContainsSelection(this IResolverContext resolverContext, string selection)
    {
        return resolverContext.GetQuerySelections().Contains(selection);
    }
    public static IEnumerable<string> GetQuerySelections(this IResolverContext resolverContext)
    {
        var fields = resolverContext.Selection.SelectionSet?.Selections.Where(x => x.Kind == HotChocolate.Language.SyntaxKind.Field) ?? [];
        return fields.GetQuerySelections();
    }
    private static IEnumerable<string> GetQuerySelections(this IEnumerable<ISelectionNode> selectionNodes)
    {
        List<string> querySelections = new List<string>();
        foreach (var selectionNode in selectionNodes)
        {
            if (((dynamic)selectionNode).SelectionSet is not null)
            {
                querySelections.Add(selectionNode.ToString().Split(' ')[0]);
                IReadOnlyList<ISelectionNode>? subSelectionNodes = ((dynamic)selectionNode).SelectionSet?.Selections;
            
                querySelections.AddRange(GetQuerySelections(subSelectionNodes?.Where(x => x.Kind == HotChocolate.Language.SyntaxKind.Field) ?? []));
           }
            else
            {
                querySelections.Add(selectionNode.ToString());
            }
         }
         return querySelections;
     }
}

Usage:

public bool FooQuery(IResolverContext resolverContext)
{
     return resolverContext.ContainsSelection(typeof(MyModel).GetProperty(nameof(MyModel.Id))!)
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文