{"id":1298,"date":"2026-03-16T20:38:48","date_gmt":"2026-03-16T23:38:48","guid":{"rendered":"https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/"},"modified":"2026-03-16T20:38:48","modified_gmt":"2026-03-16T23:38:48","slug":"graphql-dotnet-hot-chocolate-dataloaders-subscriptions","status":"publish","type":"post","link":"https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/","title":{"rendered":"GraphQL en .NET con Hot Chocolate: De los Conceptos B\u00e1sicos a DataLoaders y Subscriptions"},"content":{"rendered":"\n<p>Durante a\u00f1os trabaj\u00e9 exclusivamente con REST. Funciona, escala, es predecible \u2014 no ten\u00eda razones para cambiar. Hasta que me toc\u00f3 construir una API para una app m\u00f3vil que consum\u00eda cinco endpoints distintos para armar una sola pantalla. Ah\u00ed entend\u00ed el problema de <em>under-fetching<\/em> en carne propia. Empec\u00e9 a explorar GraphQL y, en el ecosistema .NET, el camino lleva inevitablemente a <strong>Hot Chocolate<\/strong>. En este art\u00edculo cuento c\u00f3mo funciona, con ejemplos que van desde la configuraci\u00f3n b\u00e1sica hasta DataLoaders y Subscriptions en tiempo real.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">\u00bfQu\u00e9 es GraphQL y por qu\u00e9 importa?<\/h2>\n\n\n\n<p>GraphQL es un lenguaje de consulta para APIs que expone un \u00fanico endpoint. El cliente define exactamente qu\u00e9 datos necesita \u2014 ni m\u00e1s, ni menos. Esto resuelve dos problemas cl\u00e1sicos de REST:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n  <li><strong>Over-fetching:<\/strong> el endpoint devuelve 30 campos y el cliente usa 5.<\/li>\n  <li><strong>Under-fetching:<\/strong> para armar una pantalla necesit\u00e1s llamar a 4 endpoints distintos.<\/li>\n<\/ul>\n\n\n\n<p><strong>Hot Chocolate<\/strong> es la implementaci\u00f3n de GraphQL para .NET m\u00e1s completa y activa que existe. Es modular, se integra nativamente con ASP.NET Core y Entity Framework Core, y su enfoque <em>Code-First<\/em> (definir el esquema desde clases C#) hace que el onboarding sea natural para cualquier desarrollador .NET.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">1. Configuraci\u00f3n Inicial y Queries B\u00e1sicas<\/h2>\n\n\n\n<p>El punto de entrada: registrar el servidor GraphQL en el contenedor de DI y mapear el endpoint. Una <strong>Query<\/strong> en GraphQL es el equivalente a GET en REST \u2014 define qu\u00e9 datos pueden leer los clientes.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Program.cs\nvar builder = WebApplication.CreateBuilder(args);\n\nbuilder.Services\n    .AddGraphQLServer()\n    .AddQueryType&lt;Query&gt;();\n\nvar app = builder.Build();\n\napp.MapGraphQL(); \/\/ Endpoint por defecto: \/graphql\n\napp.Run();\n\n\/\/ Query.cs\npublic class Query\n{\n    public string GetHolaMundo() => \"\u00a1Hola desde Hot Chocolate!\";\n\n    public Usuario GetUsuarioActual() => new Usuario { Id = 1, Nombre = \"Admin\" };\n}\n\npublic class Usuario\n{\n    public int Id { get; set; }\n    public string Nombre { get; set; }\n}<\/code><\/pre>\n\n\n\n<p>Hot Chocolate genera autom\u00e1ticamente el esquema GraphQL a partir de las clases C#. Al navegar a <code>\/graphql<\/code>, ten\u00e9s acceso al playground interactivo Banana Cake Pop donde pod\u00e9s explorar y ejecutar queries.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">2. Relaciones Anidadas con Projections y EF Core<\/h2>\n\n\n\n<p>Ac\u00e1 empieza la magia real. El atributo <code>[UseProjection]<\/code> intercepta la query GraphQL del cliente y genera din\u00e1micamente el <code>SELECT<\/code> SQL correspondiente. Si el cliente pide solo <code>nombre<\/code> y <code>titulo<\/code>, la base de datos devuelve solo esas columnas. Sin traer entidades completas a memoria.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class Autor\n{\n    public int Id { get; set; }\n    public string Nombre { get; set; }\n    public ICollection&lt;Libro&gt; Libros { get; set; }\n}\n\npublic class Libro\n{\n    public int Id { get; set; }\n    public string Titulo { get; set; }\n    public int AutorId { get; set; }\n}\n\npublic class Query\n{\n    [UseProjection]\n    public IQueryable&lt;Autor&gt; GetAutores([Service] AppDbContext context)\n        =&gt; context.Autores;\n}\n\n\/* Query del cliente \u2014 una sola petici\u00f3n, datos exactos:\nquery {\n  autores {\n    nombre\n    libros {\n      titulo\n    }\n  }\n}\n*\/<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">3. Filtros y Ordenamiento Din\u00e1mico<\/h2>\n\n\n\n<p>Con <code>[UseFiltering]<\/code> y <code>[UseSorting]<\/code>, el cliente puede enviar argumentos complejos de b\u00fasqueda que Hot Chocolate traduce autom\u00e1ticamente a expresiones LINQ. El orden de los atributos importa: primero Projections, luego Filtering, luego Sorting.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Program.cs \u2014 registrar las capacidades\nbuilder.Services.AddGraphQLServer()\n    .AddFiltering()\n    .AddSorting();\n\n\/\/ Query.cs\npublic class Query\n{\n    [UseProjection]\n    [UseFiltering]\n    [UseSorting]\n    public IQueryable&lt;Libro&gt; GetLibros([Service] AppDbContext context)\n        =&gt; context.Libros;\n}\n\n\/* Query del cliente con filtro y ordenamiento:\nquery {\n  libros(\n    where: { titulo: { contains: \"GraphQL\" } }\n    order: [ { id: DESC } ]\n  ) {\n    id\n    titulo\n  }\n}\n*\/<\/code><\/pre>\n\n\n\n<p>Todo esto se traduce a una sola query SQL optimizada. Sin c\u00f3digo adicional en el servidor.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">4. Mutations: Escritura de Datos<\/h2>\n\n\n\n<p>Las <strong>Mutations<\/strong> son el equivalente a POST\/PUT\/DELETE en REST. Lo interesante es que devuelven un tipo de dato (<em>Payload<\/em>), permitiendo al cliente mutar y consultar el nuevo estado en la misma operaci\u00f3n.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Program.cs\nbuilder.Services.AddGraphQLServer()\n    .AddMutationType&lt;Mutation&gt;();\n\n\/\/ Mutation.cs\npublic class Mutation\n{\n    public async Task&lt;LibroPayload&gt; CrearLibroAsync(\n        CrearLibroInput input,\n        [Service] AppDbContext context)\n    {\n        var nuevoLibro = new Libro\n        {\n            Titulo = input.Titulo,\n            AutorId = input.AutorId\n        };\n\n        context.Libros.Add(nuevoLibro);\n        await context.SaveChangesAsync();\n\n        return new LibroPayload(nuevoLibro);\n    }\n}\n\npublic record CrearLibroInput(string Titulo, int AutorId);\npublic record LibroPayload(Libro Libro);\n\n\/* Mutation del cliente \u2014 crea y consulta en una sola operaci\u00f3n:\nmutation {\n  crearLibro(input: { titulo: \"Mastering Hot Chocolate\", autorId: 1 }) {\n    libro {\n      id\n      titulo\n    }\n  }\n}\n*\/<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">5. DataLoaders: Eliminando el Problema N+1<\/h2>\n\n\n\n<p>El tal\u00f3n de Aquiles de cualquier implementaci\u00f3n GraphQL ingenua es el problema <strong>N+1<\/strong>: si consult\u00e1s 10 libros y cada libro necesita resolver su autor, termin\u00e1s con 1 query para los libros + 10 queries individuales para los autores = 11 queries en total. Con un dataset real de 1000 libros, eso es un desastre.<\/p>\n\n\n\n<p>Los <strong>DataLoaders<\/strong> resuelven esto agrupando todas las peticiones de autores en un solo lote y ejecut\u00e1ndolas en una \u00fanica query a la base de datos, con cach\u00e9 autom\u00e1tico por ciclo de vida de la petici\u00f3n.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class AutorBatchDataLoader : BatchDataLoader&lt;int, Autor&gt;\n{\n    private readonly AppDbContext _dbContext;\n\n    public AutorBatchDataLoader(\n        IBatchScheduler batchScheduler,\n        DataLoaderOptions options,\n        AppDbContext dbContext)\n        : base(batchScheduler, options)\n    {\n        _dbContext = dbContext;\n    }\n\n    protected override async Task&lt;IReadOnlyDictionary&lt;int, Autor&gt;&gt; LoadBatchAsync(\n        IReadOnlyList&lt;int&gt; keys,\n        CancellationToken cancellationToken)\n    {\n        \/\/ 1000 libros = 1 sola query con WHERE Id IN (...)\n        return await _dbContext.Autores\n            .Where(a =&gt; keys.Contains(a.Id))\n            .ToDictionaryAsync(a =&gt; a.Id, cancellationToken);\n    }\n}\n\n\/\/ Extensi\u00f3n de tipo para resolver el autor de cada libro usando el DataLoader\n[ExtendObjectType(typeof(Libro))]\npublic class LibroExtensions\n{\n    public async Task&lt;Autor&gt; GetAutorAsync(\n        [Parent] Libro libro,\n        AutorBatchDataLoader dataLoader,\n        CancellationToken cancellationToken)\n        =&gt; await dataLoader.LoadAsync(libro.AutorId, cancellationToken);\n\n    [GraphQLName(\"tituloEnMayusculas\")]\n    public string GetTituloMayusculas([Parent] Libro libro)\n        =&gt; libro.Titulo.ToUpper();\n}\n\n\/\/ Program.cs \u2014 registrar la extensi\u00f3n\n\/\/ builder.Services.AddGraphQLServer().AddType&lt;LibroExtensions&gt;();<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">6. Subscriptions: Datos en Tiempo Real<\/h2>\n\n\n\n<p>Esto es lo que REST no puede hacer de forma nativa: el cliente se suscribe a un evento y el servidor le notifica autom\u00e1ticamente cuando ocurre. Hot Chocolate implementa Subscriptions sobre WebSockets, lo que es ideal para notificaciones en vivo, dashboards en tiempo real o chats.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\/\/ Program.cs \u2014 habilitar WebSockets y Subscriptions\napp.UseWebSockets();\n\nbuilder.Services.AddGraphQLServer()\n    .AddSubscriptionType&lt;Subscription&gt;()\n    .AddInMemorySubscriptions(); \/\/ Para un solo servidor; en cluster usar Redis\n\n\/\/ Subscription.cs\npublic class Subscription\n{\n    [Subscribe]\n    [Topic(\"LibroCreado\")]\n    public Libro OnLibroCreado([EventMessage] Libro libro) =&gt; libro;\n}\n\n\/\/ En la Mutation, publicar el evento al crear un libro\npublic class Mutation\n{\n    public async Task&lt;LibroPayload&gt; CrearLibroAsync(\n        CrearLibroInput input,\n        [Service] AppDbContext context,\n        [Service] ITopicEventSender eventSender,\n        CancellationToken cancellationToken)\n    {\n        var nuevoLibro = new Libro { Titulo = input.Titulo, AutorId = input.AutorId };\n        context.Libros.Add(nuevoLibro);\n        await context.SaveChangesAsync(cancellationToken);\n\n        \/\/ Notificar a todos los clientes suscritos\n        await eventSender.SendAsync(\"LibroCreado\", nuevoLibro, cancellationToken);\n\n        return new LibroPayload(nuevoLibro);\n    }\n}\n\n\/* Suscripci\u00f3n del cliente (WebSocket):\nsubscription {\n  onLibroCreado {\n    id\n    titulo\n  }\n}\n*\/<\/code><\/pre>\n\n\n\n<p>La primera vez que vi esto funcionar en un dashboard en tiempo real, conectado a una app m\u00f3vil y una web simult\u00e1neamente, entend\u00ed por qu\u00e9 GraphQL cambi\u00f3 la forma en que pensamos las APIs.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">GraphQL vs. REST: \u00bfCu\u00e1ndo usar cada uno?<\/h2>\n\n\n\n<p>No es una competencia \u2014 son herramientas para contextos distintos. Mi criterio:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n  <li><strong>Us\u00e1 GraphQL cuando:<\/strong> ten\u00e9s m\u00faltiples clientes (web, m\u00f3vil, terceros) con necesidades de datos distintas, o cuando necesit\u00e1s tiempo real con Subscriptions.<\/li>\n  <li><strong>Us\u00e1 REST cuando:<\/strong> la API es p\u00fablica y necesita ser consumida por herramientas gen\u00e9ricas (cURL, Postman b\u00e1sico, integraciones externas simples), o cuando el equipo no tiene experiencia con GraphQL y el deadline no da margen.<\/li>\n<\/ul>\n\n\n\n<p>En proyectos complejos, tambi\u00e9n conviven: REST para endpoints p\u00fablicos y webhooks, GraphQL para el frontend propio.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusi\u00f3n<\/h2>\n\n\n\n<p>Hot Chocolate es, en mi opini\u00f3n, la implementaci\u00f3n m\u00e1s completa de GraphQL en cualquier ecosistema. La integraci\u00f3n con EF Core, los DataLoaders para resolver N+1, las Subscriptions sobre WebSockets y el enfoque Code-First lo hacen una opci\u00f3n s\u00f3lida para proyectos empresariales en .NET.<\/p>\n\n\n\n<p>Si ven\u00eds de REST y nunca probaste GraphQL, el primer paso es levantar un proyecto con la configuraci\u00f3n b\u00e1sica y explorar el playground Banana Cake Pop. La curva de aprendizaje inicial es real, pero se amortiza r\u00e1pido en proyectos con m\u00faltiples clientes o necesidades de datos complejas.<\/p>\n\n\n\n<p>\u00bfTen\u00e9s dudas sobre c\u00f3mo migrar una API REST existente a GraphQL o c\u00f3mo manejar autenticaci\u00f3n y autorizaci\u00f3n en el esquema? Dejalo en los comentarios.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Gu\u00eda completa de GraphQL en .NET con Hot Chocolate: configuraci\u00f3n inicial, Queries con Projections y EF Core, Filtering y Sorting din\u00e1mico, Mutations con Payload, DataLoaders para eliminar el problema N+1, y Subscriptions en tiempo real con WebSockets. Con ejemplos reales y cu\u00e1ndo usar GraphQL vs REST.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[1,202],"tags":[359,398,392,344,185,400,390,391,393,396,395,399,397,394],"class_list":["post-1298","post","type-post","status-publish","format-standard","hentry","category-blog","category-dotnet","tag-asp-net-core","tag-code-first","tag-dataloader","tag-ef-core","tag-entityframework","tag-filtering","tag-graphql","tag-hot-chocolate","tag-mutations","tag-n1","tag-over-fetching","tag-projections","tag-schema","tag-subscriptions"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>GraphQL en .NET con Hot Chocolate: De los Conceptos B\u00e1sicos a DataLoaders y Subscriptions &#183; devops Mauro Bernal<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/\" \/>\n<meta property=\"og:locale\" content=\"es_ES\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"GraphQL en .NET con Hot Chocolate: De los Conceptos B\u00e1sicos a DataLoaders y Subscriptions &#183; devops Mauro Bernal\" \/>\n<meta property=\"og:description\" content=\"Gu\u00eda completa de GraphQL en .NET con Hot Chocolate: configuraci\u00f3n inicial, Queries con Projections y EF Core, Filtering y Sorting din\u00e1mico, Mutations con Payload, DataLoaders para eliminar el problema N+1, y Subscriptions en tiempo real con WebSockets. Con ejemplos reales y cu\u00e1ndo usar GraphQL vs REST.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/\" \/>\n<meta property=\"og:site_name\" content=\"devops Mauro Bernal\" \/>\n<meta property=\"article:published_time\" content=\"2026-03-16T23:38:48+00:00\" \/>\n<meta name=\"author\" content=\"Mauro Bernal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@_maurobernal\" \/>\n<meta name=\"twitter:site\" content=\"@_maurobernal\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"Mauro Bernal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tiempo de lectura\" \/>\n\t<meta name=\"twitter:data2\" content=\"7 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\\\/\"},\"author\":{\"name\":\"Mauro Bernal\",\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/#\\\/schema\\\/person\\\/09c4dbdfb59b20e015c703fd19713283\"},\"headline\":\"GraphQL en .NET con Hot Chocolate: De los Conceptos B\u00e1sicos a DataLoaders y Subscriptions\",\"datePublished\":\"2026-03-16T23:38:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\\\/\"},\"wordCount\":844,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/#\\\/schema\\\/person\\\/09c4dbdfb59b20e015c703fd19713283\"},\"keywords\":[\"ASP.NET Core\",\"Code-First\",\"DataLoader\",\"EF Core\",\"EntityFramework\",\"Filtering\",\"GraphQL\",\"Hot Chocolate\",\"Mutations\",\"N+1\",\"Over-fetching\",\"Projections\",\"Schema\",\"Subscriptions\"],\"articleSection\":[\"Blog\",\"DotNet\"],\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\\\/\",\"url\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\\\/\",\"name\":\"GraphQL en .NET con Hot Chocolate: De los Conceptos B\u00e1sicos a DataLoaders y Subscriptions &#183; devops Mauro Bernal\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/#website\"},\"datePublished\":\"2026-03-16T23:38:48+00:00\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\\\/#breadcrumb\"},\"inLanguage\":\"es\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Portada\",\"item\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"GraphQL en .NET con Hot Chocolate: De los Conceptos B\u00e1sicos a DataLoaders y Subscriptions\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/\",\"name\":\"devops Mauro Bernal\",\"description\":\"Cuando tu trabajo es hacer que las cosas funcionen bien...\",\"publisher\":{\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/#\\\/schema\\\/person\\\/09c4dbdfb59b20e015c703fd19713283\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"es\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/maurobernal.com.ar\\\/blog\\\/#\\\/schema\\\/person\\\/09c4dbdfb59b20e015c703fd19713283\",\"name\":\"Mauro Bernal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"es\",\"@id\":\"https:\\\/\\\/i0.wp.com\\\/maurobernal.com.ar\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/07\\\/logo-maurobernal.png?fit=1740%2C1740&ssl=1\",\"url\":\"https:\\\/\\\/i0.wp.com\\\/maurobernal.com.ar\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/07\\\/logo-maurobernal.png?fit=1740%2C1740&ssl=1\",\"contentUrl\":\"https:\\\/\\\/i0.wp.com\\\/maurobernal.com.ar\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/07\\\/logo-maurobernal.png?fit=1740%2C1740&ssl=1\",\"width\":1740,\"height\":1740,\"caption\":\"Mauro Bernal\"},\"logo\":{\"@id\":\"https:\\\/\\\/i0.wp.com\\\/maurobernal.com.ar\\\/blog\\\/wp-content\\\/uploads\\\/2023\\\/07\\\/logo-maurobernal.png?fit=1740%2C1740&ssl=1\"},\"description\":\"Desarrollo de Sistemas en .Net, IT Callcenters, DBA de SQL Server, Mikrotik, Pentest y T\u00e9cnico consultor de Sistemas Bejerman\",\"sameAs\":[\"https:\\\/\\\/maurobernal.com.ar\",\"https:\\\/\\\/x.com\\\/_maurobernal\",\"https:\\\/\\\/youtube.com\\\/maurobernal\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"GraphQL en .NET con Hot Chocolate: De los Conceptos B\u00e1sicos a DataLoaders y Subscriptions &#183; devops Mauro Bernal","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/","og_locale":"es_ES","og_type":"article","og_title":"GraphQL en .NET con Hot Chocolate: De los Conceptos B\u00e1sicos a DataLoaders y Subscriptions &#183; devops Mauro Bernal","og_description":"Gu\u00eda completa de GraphQL en .NET con Hot Chocolate: configuraci\u00f3n inicial, Queries con Projections y EF Core, Filtering y Sorting din\u00e1mico, Mutations con Payload, DataLoaders para eliminar el problema N+1, y Subscriptions en tiempo real con WebSockets. Con ejemplos reales y cu\u00e1ndo usar GraphQL vs REST.","og_url":"https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/","og_site_name":"devops Mauro Bernal","article_published_time":"2026-03-16T23:38:48+00:00","author":"Mauro Bernal","twitter_card":"summary_large_image","twitter_creator":"@_maurobernal","twitter_site":"@_maurobernal","twitter_misc":{"Escrito por":"Mauro Bernal","Tiempo de lectura":"7 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/#article","isPartOf":{"@id":"https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/"},"author":{"name":"Mauro Bernal","@id":"https:\/\/maurobernal.com.ar\/blog\/#\/schema\/person\/09c4dbdfb59b20e015c703fd19713283"},"headline":"GraphQL en .NET con Hot Chocolate: De los Conceptos B\u00e1sicos a DataLoaders y Subscriptions","datePublished":"2026-03-16T23:38:48+00:00","mainEntityOfPage":{"@id":"https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/"},"wordCount":844,"commentCount":0,"publisher":{"@id":"https:\/\/maurobernal.com.ar\/blog\/#\/schema\/person\/09c4dbdfb59b20e015c703fd19713283"},"keywords":["ASP.NET Core","Code-First","DataLoader","EF Core","EntityFramework","Filtering","GraphQL","Hot Chocolate","Mutations","N+1","Over-fetching","Projections","Schema","Subscriptions"],"articleSection":["Blog","DotNet"],"inLanguage":"es","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/","url":"https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/","name":"GraphQL en .NET con Hot Chocolate: De los Conceptos B\u00e1sicos a DataLoaders y Subscriptions &#183; devops Mauro Bernal","isPartOf":{"@id":"https:\/\/maurobernal.com.ar\/blog\/#website"},"datePublished":"2026-03-16T23:38:48+00:00","breadcrumb":{"@id":"https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/#breadcrumb"},"inLanguage":"es","potentialAction":[{"@type":"ReadAction","target":["https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/maurobernal.com.ar\/blog\/graphql-dotnet-hot-chocolate-dataloaders-subscriptions\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Portada","item":"https:\/\/maurobernal.com.ar\/blog\/"},{"@type":"ListItem","position":2,"name":"GraphQL en .NET con Hot Chocolate: De los Conceptos B\u00e1sicos a DataLoaders y Subscriptions"}]},{"@type":"WebSite","@id":"https:\/\/maurobernal.com.ar\/blog\/#website","url":"https:\/\/maurobernal.com.ar\/blog\/","name":"devops Mauro Bernal","description":"Cuando tu trabajo es hacer que las cosas funcionen bien...","publisher":{"@id":"https:\/\/maurobernal.com.ar\/blog\/#\/schema\/person\/09c4dbdfb59b20e015c703fd19713283"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/maurobernal.com.ar\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"es"},{"@type":["Person","Organization"],"@id":"https:\/\/maurobernal.com.ar\/blog\/#\/schema\/person\/09c4dbdfb59b20e015c703fd19713283","name":"Mauro Bernal","image":{"@type":"ImageObject","inLanguage":"es","@id":"https:\/\/i0.wp.com\/maurobernal.com.ar\/blog\/wp-content\/uploads\/2023\/07\/logo-maurobernal.png?fit=1740%2C1740&ssl=1","url":"https:\/\/i0.wp.com\/maurobernal.com.ar\/blog\/wp-content\/uploads\/2023\/07\/logo-maurobernal.png?fit=1740%2C1740&ssl=1","contentUrl":"https:\/\/i0.wp.com\/maurobernal.com.ar\/blog\/wp-content\/uploads\/2023\/07\/logo-maurobernal.png?fit=1740%2C1740&ssl=1","width":1740,"height":1740,"caption":"Mauro Bernal"},"logo":{"@id":"https:\/\/i0.wp.com\/maurobernal.com.ar\/blog\/wp-content\/uploads\/2023\/07\/logo-maurobernal.png?fit=1740%2C1740&ssl=1"},"description":"Desarrollo de Sistemas en .Net, IT Callcenters, DBA de SQL Server, Mikrotik, Pentest y T\u00e9cnico consultor de Sistemas Bejerman","sameAs":["https:\/\/maurobernal.com.ar","https:\/\/x.com\/_maurobernal","https:\/\/youtube.com\/maurobernal"]}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack-related-posts":[],"jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/posts\/1298","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/comments?post=1298"}],"version-history":[{"count":0,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/posts\/1298\/revisions"}],"wp:attachment":[{"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/media?parent=1298"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/categories?post=1298"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/maurobernal.com.ar\/blog\/wp-json\/wp\/v2\/tags?post=1298"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}