Mostrando entradas con la etiqueta nuget. Mostrar todas las entradas
Mostrando entradas con la etiqueta nuget. Mostrar todas las entradas

viernes, 27 de marzo de 2026

Programando en C# no. 14: gRPC con .NET

 

En el post pasado vimos cómo crear un sencillo proyecto tipo cliente-servidor con .Net y gRPC.

Continuando con el tema vamos a recordar un poco.

  • gRPC es una tecnología moderna ideal para microservicios de alto rendimiento, escalables y seguros. 
  • Protobuff es el mecanismo de serialización que usa gRPC
  • HTTP/2 como protocolo de comunicación, el cual prioriza solicitudes, permite la comprensión de encabezados, multiplexación (múltiples llamadas simultáneas) y tiene mayor seguridad.

Creando un proyecto cliente-servidor en .Net (C#)

Crearemos un proyecto cliente-servidor en el cual el cliente mandará un número entero y el servidor evaluará si es mayor o no a 100.

1. Creamos nuestro proyecto servidor:

$ dotnet new grpc -o GrpcServer

2. Entramos al directorio creado y agregamos los siguientes Nuget:

Por línea de comandos:

$ dotnet add package Grpc.AspNetCore
$ dotnet add package Google.Protobuf
$ dotnet add package Grpc.Tools

Desde el archivo ``GrpcServer.csproj``:

<ItemGroup>
  <PackageReference Include="Grpc.AspNetCore" Version="2.60.0" />
  <PackageReference Include="Google.Protobuf" Version="3.25.0" />
  <PackageReference Include="Grpc.Tools" Version="2.60.0" PrivateAssets="All" />
</ItemGroup>

Ejecutar esto para descargar paquetes:

$ dotnet restore

3. Crearemos un archivo *.proto, el cual tendrá el un servicio llamado Validar y un método llamado EsMayorQue100 que recibirá un NumeroRequest y devolverá un NumeroResponse.

Protos\validar.proto

syntax = "proto3";

option csharp_namespace = "GrpcDemo";

package validar;

service Validar {
  rpc EsMayorQue100 (NumeroRequest) returns (NumeroResponse);
}

message NumeroRequest {
  int32 valor = 1;
}

message NumeroResponse {
  bool es_mayor = 1;
}

4. Editamos el archivo ``GrpcServer.csproj`` para agregar el archivo *.proto:

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>net10.0</TargetFramework>
    <Nullable>enable</Nullable>
    <ImplicitUsings>enable</ImplicitUsings>
  </PropertyGroup>

  <ItemGroup>
    <!--<Protobuf Include="Protos\greet.proto" GrpcServices="Server" />-->
	<Protobuf Include="Protos\validar.proto" GrpcServices="Server" />
  </ItemGroup>

  <ItemGroup>
    <PackageReference Include="Google.Protobuf" Version="3.34.1" />
    <PackageReference Include="Grpc.AspNetCore" Version="2.76.0" />
    <PackageReference Include="Grpc.Tools" Version="2.78.0">
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
      <PrivateAssets>all</PrivateAssets>
    </PackageReference>
  </ItemGroup>

</Project>

5. Creamos el servicio:

ValidarService.cs

using GrpcDemo;
using Grpc.Core;

public class ValidarService : Validar.ValidarBase
{
    public override Task<NumeroResponse> EsMayorQue100(NumeroRequest request, ServerCallContext context)
    {
        bool resultado = request.Valor > 100;
        return Task.FromResult(new NumeroResponse { EsMayor = resultado });
    }
}

6. El programa principal del servidor será el siguiente:

Program.cs

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddGrpc();
var app = builder.Build();
app.MapGrpcService<ValidarService>();
app.Run();

Ahora vamos por el proyecto cliente.

7. Creamos el proyecto:

$ dotnet new console -o GrpcClient

8. Nos ubicamos en el directorio creado. Y configuramos el archivo ``GrpcClient.csproj``:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net10.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  
  
  
  <ItemGroup>
  <Protobuf Include="..\GrpcServer\Protos\validar.proto" GrpcServices="Client" />
</ItemGroup>
<ItemGroup>
  <PackageReference Include="Grpc.Net.Client" Version="2.60.0" />
  <PackageReference Include="Google.Protobuf" Version="3.34.1" />
  <PackageReference Include="Grpc.Tools" Version="2.78.0" PrivateAssets="All" />
</ItemGroup>


</Project>

Ejecutar esto para descargar paquetes:

$ dotnet restore

9. El programa principal del cliente será este:

Program.cs

using Grpc.Net.Client;
using GrpcDemo;

class Program
{
    static async Task Main(string[] args)
    {
        using var channel = GrpcChannel.ForAddress("http://localhost:5203");
        var client = new Validar.ValidarClient(channel);

        Console.Write("Ingrese un número: ");
        int numero = int.Parse(Console.ReadLine());

        var response = await client.EsMayorQue100Async(new NumeroRequest { Valor = numero });
        Console.WriteLine($"¿Es mayor a 100? {response.EsMayor}");
    }
}

10. Ejecutamos el servidor:

$ dotnet run --project GrpcServer

11. Ejecutamos el cliente:

$ dotnet run --project GrpcClient

Si todo va bien veremos esto en el servidor:

info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://localhost:5203
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]

Del lado del cliente:

Ingrese un número: 23
¿Es mayor a 100? False

Podemos modificar el programa cliente de tal manera que solicite salir o continuar.

using Grpc.Net.Client;
using GrpcDemo;

class Program
{
    static async Task Main(string[] args)
    {
        using var channel = GrpcChannel.ForAddress("http://localhost:5203");
        var client = new Validar.ValidarClient(channel);

        string continuar;
        do
        {
            Console.Write("Ingrese un número: ");
            int numero = int.Parse(Console.ReadLine());

            var response = await client.EsMayorQue100Async(new NumeroRequest { Valor = numero });
            Console.WriteLine($"¿Es mayor a 100? {response.EsMayor}");
            Console.WriteLine();

            Console.Write("¿Desea continuar [s-n]? ");
            continuar = Console.ReadLine()?.Trim().ToLower();
            Console.WriteLine();

        } while (continuar == "s");

        Console.WriteLine("Adios");
    }
}

Salida:

Ingrese un número: 23
¿Es mayor a 100? False

¿Desea continuar [s-n]? s 
Ingrese un número: 200
¿Es mayor a 100? True 

¿Desea continuar [s-n]? n 
Adios

¡Hemos creado un proyecto cliente-servidor con gRPC y .NET!

Continuaremos con este tema en próximas entregas.

Enlaces:

https://codemonkeyjunior.blogspot.com/2026/02/grpc-una-alternativa-para-servicios-de.html
https://alquimistadecodigo.blogspot.com/2026/03/grpc-con-go.html
https://alquimistadecodigo.blogspot.com/2026/03/grpc-con-python.html


sábado, 14 de marzo de 2026

Serilog: registrando eventos en .Net

Para quienes llevan tiempo programando saben que llevar un registro de eventos de nuestras aplicaciones (web, principalmente) es muy importante para dar soporte a ciertas incidencias que pudieran presentarse.

Los loggers son registros que contienen la fecha y hora de ciertos eventos. Estos son importantes cuando queremos saber qué acción disparó el usuario y, en ciertos casos, el resultado que arrojó.

El resultado puede ser satisfactorio o pueden presentarse errores que debemos atender.

.NET nos permite usar librerías como Serilog para realizar estas actividades. La documentación oficial nos dice:

"Serilog proporciona registro de diagnóstico en archivos, la consola y otros lugares".

Además promete ser fácil de configurar y usar.

"Es fácil de configurar, tiene una API limpia y es portable entre las plataformas .NET más recientes".
"Es útil incluso en las aplicaciones más sencillas, la compatibilidad de Serilog con el registro estructurado destaca al instrumentar aplicaciones y sistemas complejos, distribuidos y asíncronos".

Instalando Serilog

La instalación de Serilog la haremos gracias a los NuGets. Podemos abrir una terminal para hacerlo:

$ dotnet add package Serilog
$ dotnet add package Serilog.Sinks.Console

Esto siguiendo los pasos del sitio oficial de Serilog.

El sitio de Nuget nos da solo esta acción:

$ dotnet add package Serilog --version 4.3.1

Nos quedaremos con esta última opción de instalación.

Empezando con Serilog

1. Crearemos una aplicación de consola y nos ubicamos en el directorio creado:

$ dotnet new console -n DemoSerilog
$ cd DemoSerilog

2. Agregamos Serilog:

$ dotnet add package Serilog --version 4.3.1

3. Validamos la instalación:

$ dotnet list package

Nota: En caso de necesitar más paquetes deberás remover Serilog e instalar todos los siguientes paquetes:

$ dotnet remove package Serilog

$ dotnet add package Serilog
$ dotnet add package Serilog.Sinks.Console
$ dotnet add package Serilog.Sinks.File
$ dotnet add package Serilog.Settings.Configuration

4. Abrimos el Program.cs y lo editamos.

using System;
using Serilog;

/**
 * @author Codemonkey Junior
 * @date 2026/03/14
 *
 */
class Program
{
     public Program()
    {
        Console.WriteLine("Objeto 'Program' creado e inicializado.");
    }

    ~Program() { }

    public static void Main(string[] args)
    {
        using var log = new LoggerConfiguration()
        .WriteTo.Console()
        .WriteTo.File("log.txt")
        .CreateLogger();
        
        log.Information("Hola, Serilog!");
        Log.Information("Nuestra primera configuracion Serilog.");
    }
}

5. Construimos el proyecto y lo ejecutamos:

$ dotnet build
$ dotnet run

Salida:

[14:17:07 INF] Hola, Serilog!
[14:17:07 INF] Nuestra primera configuracion Serilog.

NLog: alternativa a Serilog

El proyecto https://nlog-project.org es una alternativa a Serilog. El cual es:

..."una plataforma de registro flexible y gratuita para diversas plataformas .NET, incluyendo .NET Standard. NLog facilita la escritura en múltiples destinos (consola, archivo, base de datos, etc.) y permite modificar la configuración de registro sobre la marcha".

Esta alternativa a Serilog la veremos en otra entrega.

Hemos visto que serilog es una biblioteca de registro de diagnóstico para aplicaciones .NET. El cual es fácil de configurar, tiene una API limpia y se ejecuta en todas las plataformas .NET recientes.

También hemos visto cómo instalar, listar y remover paquetes Nuget. En próximas entregas veremos más a fondo esta librería.

Enlaces:

https://serilog.net/
Top 13 Libraries in .NET With Alteratives
https://github.com/serilog/serilog/wiki/Getting-Started



sábado, 29 de noviembre de 2025

Entity Framework: un ORM para .NET

Para los programadores Java que han usado Hibernate o cualquier otro ORM sabrán que son herramientas muy útiles para el mapeo de tablas y clases Java. Pues ahorran una gran cantidad de código y horas de esfuerzo.

.NET tiene un ORM llamado EntityFramework (EF), el cual es:

"... un mapeador objeto-relacional (ORM) de Microsoft para .NET que permite a los desarrolladores interactuar con bases de datos relacionales usando objetos de C# en lugar de escribir consultas SQL".

Un ORM nos permite manipular la información de las tablas como objetos. Esto nos evita tener que lidiar con SQL nativo.

Al usar EntityFramework podemos:

  • Mapear las tablas de nuestra base de datos como si fueran clases. 
  • Manipular la información de las tablas sin necesidad de sentencias SQL. 
  • Contar con las operaciones CRUD ya "integradas". 
  • Compatibilidad con LINQ (un lenguaje para realizar consultas con C#). 
  • Permitir conectarnos distintas fuentes de datos como MS SQL Server, MySQL, PostgreSQL, etc. 
  • Simplificar nuestro código.

También debemos tener cuidado de:

  1. Observar el rendimiento de las consultas. 
  2. Entender cómo se usa LINQ.

Al usar un ORM debemos entender:

  1. Qué base de datos vamos a usar. 
  2. Qué es lo que queremos mapear (tablas). 
  3. Convertir la estructura de las tablas a objetos (mapeo). 
  4. Qué operaciones vamos a realizar sobre esos objetos (operaciones CRUD).

Comenzando con EntityFramework

Crearemos una sencilla aplicación C# usando el ORM EntityFramework.

Requisitos:

  • Contar con la herramienta dotnet instalada. 
  • Contar con MariaDB instalado. 
  • Tener nociones de C#.

1. Es necesario contar con una base de datos ("cursomariadb") y al menos una tabla en la misma (persons).

CREATE OR REPLACE TABLE persons(
personid int, 
lastname varchar(255), 
firstname varchar(255), 
address varchar(255), 
city varchar(255)
);

3. Crearemos el proyecto con la herramienta dotnet y nos ubicaremos en el directorio creado:

$ dotnet new console -n DemoEFMariaDB
$ cd DemoEFMariaDB

4. Instalar los paquetes nugets necesarios:

$ dotnet add package Microsoft.EntityFrameworkCore --version 8.0.0
$ dotnet add package Pomelo.EntityFrameworkCore.MySql --version 8.0.0

Con estos instalamos EntityFramework y el conector a MariaDB (recordar que es un fork de MySQL).

5. Dentro del directorio del proyecto crearemos una carpeta llamada Model y dentro una clase C# que homologue a la tabla.

Person.cs

namespace Model
{
    public class Person
    {
        public int PersonId { get; set; }

        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string Address { get; set; }

        public string City { get; set; }

        public Person()
        {
            PersonId = 0;
            LastName = string.Empty;
            FirstName = string.Empty;
            Address = string.Empty;
            City = string.Empty;
        }

    }

}

6. Ahora crearemos una clase contexto para la conexión a la base de datos.

AppDbContext.cs

using Microsoft.EntityFrameworkCore;
using Model;


public class AppDbContext : DbContext
{
    public DbSet<Person> Persons { get; set; }

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        optionsBuilder.UseMySql(
            "server=localhost;database=cursomariadb;user=root;password=secreta",
            new MySqlServerVersion(new Version(10, 11, 2)) 
        );
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Person>().ToTable("persons"); 
        modelBuilder.Entity<Person>().HasKey(p => p.PersonId);
    }
}

7. Modificaremos el programa principal del proyecto para agregar las operaciones CRUD. Comenzaremos con la operación INSERT INTO .

Program.cs

using System;
using System.Linq;
using Model;

class Program
{
    static void Main()
    {
        using var db = new AppDbContext();

        // INSERT
        var newPerson = new Person
        {
            PersonId = 4,
            FirstName = "Juan",
            LastName = "Pérez",
            Address = "Calle Falsa 123",
            City = "CDMX"
        };
        db.Persons.Add(newPerson);
        db.SaveChanges();
        Console.WriteLine("Insertado correctamente.");
    }

}

Seguiremos con la instrucción SELECT:

// SELECT
        var persons = db.Persons.ToList();
        Console.WriteLine("Listado de personas:");
        foreach (var p in persons)
        {
            Console.WriteLine($"{p.PersonId} - {p.FirstName} {p.LastName} - {p.City}");
        }

Ahora con la instrucción UPDATE:

 // UPDATE
        var personToUpdate = db.Persons.FirstOrDefault(p => p.PersonId == 4);
        if (personToUpdate != null)
        {
            personToUpdate.City = "Guadalajara";
            db.SaveChanges();
            Console.WriteLine("Actualizado correctamente.");
        }

Finalmente con la instrucción DELETE:

// DELETE
        var personToDelete = db.Persons.FirstOrDefault(p => p.PersonId == 4);
        if (personToDelete != null)
        {
            db.Persons.Remove(personToDelete);
            db.SaveChanges();
            Console.WriteLine("Eliminado correctamente.");
        }

Código completo:

using System;
using System.Linq;
using Model;

class Program
{
    static void Main()
    {
        using var db = new AppDbContext();

        // INSERT
        var newPerson = new Person
        {
            PersonId = 4,
            FirstName = "Juan",
            LastName = "Pérez",
            Address = "Calle Falsa 123",
            City = "CDMX"
        };
        db.Persons.Add(newPerson);
        db.SaveChanges();
        Console.WriteLine("Insertado correctamente.");

        // SELECT
        var persons = db.Persons.ToList();
        Console.WriteLine("Listado de personas:");
        foreach (var p in persons)
        {
            Console.WriteLine($"{p.PersonId} - {p.FirstName} {p.LastName} - {p.City}");
        }

        // UPDATE
        var personToUpdate = db.Persons.FirstOrDefault(p => p.PersonId == 4);
        if (personToUpdate != null)
        {
            personToUpdate.City = "Guadalajara";
            db.SaveChanges();
            Console.WriteLine("Actualizado correctamente.");
        }

        // DELETE
        var personToDelete = db.Persons.FirstOrDefault(p => p.PersonId == 4);
        if (personToDelete != null)
        {
            db.Persons.Remove(personToDelete);
            db.SaveChanges();
            Console.WriteLine("Eliminado correctamente.");
        }
    }
}

8. Ejecutamos la aplicación:

$ dotnet run

Salida:

Insertado correctamente.
Listado de personas:
1 - Carmen Moreno - EDOMEX
2 - Jimena Torres - Toluca
3 - Torres Manuel - Cuajimalpa
4 - Juan Pérez - CDMX
Actualizado correctamente.

¡Hemos creado una aplicación C# con EntityFramework !

Conclusiones:

  • EntityFramework es una herramienta poderosa que nos ahorra tiempo de desarrollo simplificando el acceso datos y su manipulación. 
  • LINQ hace que las operaciones sobre las tablas sea más sencillo.
  • Su soporte a varias fuentes de datos es muy útil y no nos limita a usar una sola.
  • La complejidad de código se reduce abruptamente, ¡parece magia!
  • Aunque tiene muchas ventajas hay que considerar el rendimiento cuando existe una gran cantidad de datos.

Seguiremos con esta serie sobre C#.

Enlaces:

https://andresledo.es/csharp/entity-framework-core/
https://medium.com/@ravipatel.it/a-beginners-guide-to-entity-framework-core-ef-core-5cde48fc7f7a
https://codemonkeyjunior.blogspot.com/2025/08/programando-en-c-no-9-usando-nuget.html
https://codemonkeyjunior.blogspot.com/2019/06/instalar-paquetes-nuget-con-dotnet.html
https://es.wikipedia.org/wiki/Language_Integrated_Query
https://blog.georgekosmidis.net/using-mariadb-in-an-aspnet-core-api-with-entity-framework-core.html
https://www.entityframeworktutorial.net/
https://www.learnentityframeworkcore.com/
https://learn.microsoft.com/es-es/ef/

domingo, 17 de agosto de 2025

Programando en C# no. 9 (usando Nuget)

En un anterior post hablamos sobre Nuget. El cual es el administrador de paquetes para .NET.

Con Nuget podemos:

  1. Consumir paquetes de terceros. 
  2. Crear nuestros paquetes. 
  3.  Publicar nuestros paquetes.

Nuget está incluido en el .Net Core. Abriremos una consola y teclearemos lo siguiente:

$ mkdir codemonkey 
$ cd codemonkey
$ dotnet new console

Nos ubicaremos en el proyecto creado y listaremos los paquetes:

$ dotnet list package

Mostrará un mensaje indicando que no hay paquetes asociados al proyecto.

Si queremos instalar un paquete podemos hacerlo con Nuget.

El sitio https://www.nuget.org/ tiene un buscador de paquetes. Si queremos, por ejemplo, instalar un conector de BD de MySQL podemos buscarlo. Si lo encuentra, damos clic al enlace y nos mostrará la forma de instalarlo desde dotnet.

Instalando el paquete de MySQL:

$ dotnet add package MySqlConnector --version 2.4.0

Ahora listamos el paquete:

$ dotnet list package

El sitio también provee de ejemplos de cómo usarlo (en algunos paquetes):

// set these values correctly for your database server
var builder = new MySqlConnectionStringBuilder
{
	Server = "your-server",
	UserID = "database-user",
	Password = "P@ssw0rd!",
	Database = "database-name",
};

// open a connection asynchronously
using var connection = new MySqlConnection(builder.ConnectionString);
await connection.OpenAsync();

// create a DB command and set the SQL statement with parameters
using var command = connection.CreateCommand();
command.CommandText = @"SELECT * FROM orders WHERE order_id = @OrderId;";
command.Parameters.AddWithValue("@OrderId", orderId);

// execute the command and read the results
using var reader = await command.ExecuteReaderAsync();
while (reader.Read())
{
	var id = reader.GetInt32("order_id");
	var date = reader.GetDateTime("order_date");
	// ...
}

Para ASP .Net tendríamos:

var builder = WebApplication.CreateBuilder(args);

// use AddMySqlDataSource to configure MySqlConnector
builder.Services.AddMySqlDataSource(builder.Configuration.GetConnectionString("Default"));

var app = builder.Build();

// use dependency injection to get a MySqlConnection in minimal APIs or in controllers
app.MapGet("/", async (MySqlConnection connection) =>
{
    // open and use the connection here
    await connection.OpenAsync();
    await using var command = connection.CreateCommand();
    command.CommandText = "SELECT name FROM users LIMIT 1";
    return "Hello World: " + await command.ExecuteScalarAsync();
});

app.Run();

Nuget nos permite encontrar, agregar y compartir paquetes para nuestras aplicaciones. Como desarrolladores sabemos que muchas veces un paquete puede ahorrarnos horas o días (e incluso más tiempo) de desarrollo.

Ejemplo. Queremos hacer una sencilla gráfica, pero nos llevaría bastante tiempo crear un paquete que nos permita hacerlo. La solución sería buscarlo e instalarlo.

La opción ideal sería ScottPlot, ya que es una biblioteca de gráficos similar a Matplotlib. La cual ofrece un equilibrio ideal entre facilidad de uso, rendimiento, integración nativa y documentación extensa. Eso es lo que buscamos.

La instalaremos:

$ dotnet add package ScottPlot --version 5.0.55

Si la instalación fue correcta, saldrá un mensaje indicando que ya lo tenemos integrado a nuestro proyecto. Usaremos el código de ejemplo:

Program.cs

double[] dataX = { 1, 2, 3, 4, 5 };
double[] dataY = { 1, 4, 9, 16, 25 };

ScottPlot.Plot myPlot = new();
myPlot.Add.Scatter(dataX, dataY);
myPlot.SavePng("quickstart.png", 400, 300);

Código completo:

Program.cs

using System;
using ScottPlot;


class Program
{

    public static void Main(string[] args)
    {
        Test();
    }


   private static void Test()
   {
       double[] dataX = { 1, 2, 3, 4, 5 };
       double[] dataY = { 1, 4, 9, 16, 25 };

       ScottPlot.Plot myPlot = new();
       myPlot.Add.Scatter(dataX, dataY);
       myPlot.SavePng("quickstart.png", 400, 300);
       Console.WriteLine("Gráfico creado.");
   }

}

Compilamos y ejecutamos:

$ dotnet build
$ dotnet run

Si ejecutó correctamente la aplicación, entonces se creará un gráfico llamado ``quickstart.png``.

En conclusión, si eres desarrollador .NET, entonces con Nuget encontrarás los paquetes necesarios para tus aplicaciones.

Enlaces:

https://www.nuget.org/
https://learn.microsoft.com/es-es/nuget/what-is-nuget
https://codemonkeyjunior.blogspot.com/2019/06/instalar-paquetes-nuget-con-dotnet.html



Jai un lenguaje de programación inspirado en C++

Hoy hablaremos de un nuevo lenguaje de programación llamado Jai . Se trata de un lenguaje de programación que está desarrolland...

Etiquetas

Archivo del blog