En la primera parte vimos algunos de los componentes muy utilizados en aplicaciones. Ahora veremos algunos mas:
FluentMigrator or DbUp
Es una buena alternativa para ejecutar el código EntityFramework, las primeras migraciones, tanto FluentMigrator como DbUp harán un trabajo excelente.
DbUp funciona mejor con scripts simples y SQL sin formato. Crea una aplicación de consola y agrega archivos SQL como recursos integrados. Algún código simple en Program.cs ejecutará sus scripts de migración en orden, fácil de integrar en una canalización de DevOps.
static int Main(string[] args) { var connectionString = args.FirstOrDefault(); //or some configuration var upgrader = DeployChanges.To .SqlDatabase(connectionString) .WithScriptsEmbeddedInAssembly(Assembly.GetExecutingAssembly()) .LogToConsole() .Build(); var result = upgrader.PerformUpgrade(); //omitted error handling... return 0; }
FluentMigrator tiene un concepto similar con un enfoque más orientado al código. En lugar de agregar scripts sin procesar, crearemos pequeñas clases para cada migración. Brinda más flexibilidad en la creación de migraciones (ahorra recordar la sintaxis sql de creación de clave externa) y permite escenarios de migración ascendente / descendente más completos.
using FluentMigrator; namespace Migrations { [Migration(20180430121800)] public class AddLogTable : Migration { public override void Up() { Create.Table("Log") .WithColumn("Id").AsInt64().PrimaryKey().Identity() .WithColumn("Text").AsString(); } public override void Down() { Delete.Table("Log"); } } }
CsvHelper
CsvHelper el paquete número uno para leer y escribir archivos csv. La biblioteca flexible como para que pueda crear clases y reglas de mapeo personalizadas para sus clases de C# o usar los métodos de fila y columna de bajo nivel directamente.
//import csv to a class using (var reader = new StreamReader("importfile.csv")) using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) { csv.Context.RegisterClassMap<YourClassMap>(); //optionally use a mapping class var records = csv.GetRecords<YourClass>(); } //use a mapping class public class YourClass { public int Id { get; set; } public string Name { get set; } } public sealed class YourClassMap : ClassMap<YourClass> { public FooMap() { Map(m => m.Id).Name("Identifier"); //overrider column names and more Map(m => m.Name).Name("TheName"); } } //or access columns directly using (var csv = new CsvReader(reader, CultureInfo.InvariantCulture)) { csv.ReadHeader(); while (csv.Read()) { var id csv.GetField<int>("Id"), var name = csv.GetField("Name"); } }
Hashids
Hashids, su versión para .NET, genera identificadores de cadena únicos y cortos a partir de números enteros, similares a los identificadores de video de YouTube. Es ideal para convertir uno o más enteros en un único hash corto no secuencial para usar en URL y compartir.
var hashids = new Hashids("example salt"); //creates "R9tGSE" hash var id = hashids.Encode(1, 2, 3); //decodes "R9tGSE" back into int[] {1, 2, 3} var numbers = hashids.Decode(id);
Humanizer
Siempre la conversión de fechas es un dolor de cabeza. Humanizer es para convertir fechas, números, enumeraciones y más en cadenas legibles para humanos. Admite muchos tipos de datos y se puede utilizar con varios idiomas.
//These are some methods I use all the time, check out the documentation for the full list //dates DateTime.UtcNow.AddHours(-25).Humanize() => "yesterday" DateTime.UtcNow.AddHours(4).Humanize() => "4 hours from now" //timespan TimeSpan.FromDays(16).Humanize() => "2 weeks" //Pluralize and singularize "Dog".Pluralize() => "Dogs" "Dogs".Singularize() => "Dog" //truncate "Long text to truncate".Truncate(10) => "Long text…"
Bogus
Bogus es un generador de datos fake para .NET. Crear datos para pruebas siempre es aburrido y lleva tiempo, pero Bogus no alivia un poco de ese dolor.
Bogus nos permite mapear nuestras clases de C# a datos falsos para generar rápidamente una gran cantidad de datos. También es posible acceder a los métodos subyacentes directamente y generar un número de teléfono, una dirección de correo electrónico, etc. a pedido.
//map a class var userIds = 0; var testUsers = new Faker<User>() .RuleFor(b => b.Id, (f, u) => userIds++) .RuleFor(u => u.FirstName, (f, u) => f.Name.FirstName(u.Gender)) .RuleFor(u => u.LastName, (f, u) => f.Name.LastName(u.Gender)) .RuleFor(u => u.Avatar, f => f.Internet.Avatar()) .RuleFor(u => u.UserName, (f, u) => f.Internet.UserName(u.FirstName, u.LastName)) .RuleFor(u => u.Email, (f, u) => f.Internet.Email(u.FirstName, u.LastName)); //generate users var user = testUsers.Generate(); //use methods directly var faker = new Faker("en"); faker.Internet.DomainName(); //eg "sylvester.com" faker.Company.Bs().Dump(); // eg "enable leading-edge architectures"
FluentValidation
FluentValidation es una biblioteca .NET para crear reglas de validación fuertemente tipadas. Hasta hace unos años para validar usaba dataannotations, pero desde que descubrí esta librería no volví a usar la anterior. Lo más interesante es que las validaciones de los objetos quedan totalmente desacoplados de ellos. Extraordinario!!!.
public class CustomerValidator : AbstractValidator<Customer> { public CustomerValidator() { RuleFor(x => x.Surname).NotEmpty(); RuleFor(x => x.Forename).NotEmpty().WithMessage("Please specify a first name"); RuleFor(x => x.Discount).NotEqual(0).When(x => x.HasDiscount); RuleFor(x => x.Address).Length(20, 250); RuleFor(x => x.Postcode).Must(BeAValidPostcode).WithMessage("Please specify a valid postcode"); } private bool BeAValidPostcode(string postcode) { // custom postcode validating logic goes here } }
AutoMapper
Automapper se describe así mismo como un mapeador de objeto a objeto basado en convenciones. Utiliza una API de configuración fluida para definir una estrategia de mapeo objeto-objeto. Mediante un algoritmo de coincidencia basado en convenciones hace coincidir los valores de origen con los de destino.
AutoMapper está orientado a escenarios de proyección de modelos para convertir modelos de objetos complejos a DTO y otros objetos simples, cuyo diseño es más adecuado para serialización, comunicación, mensajería o simplemente una capa anticorrupción entre el dominio y la capa de aplicación entre otros.
var mapper = config.CreateMapper(); // or var mapper = new Mapper(config); OrderDto dto = mapper.Map<OrderDto>(order);
Conclusión
Hasta acá la lista mas importante de los que uso, no quiere decir que sean los únicos, tal vez en siguientes post les cuente algunos Ases en la manga. Recuerden que todas esas librerías deben ser usadas para situaciones particulares. Si me olvido de alguno, por favor déjenmelo en los comentarios. ¡Gracias!