Selección dinámica de datos
Clase 16 de 26 • Curso de Manejo de Datos en C# con LINQ
Contenido del curso
Clase 16 de 26 • Curso de Manejo de Datos en C# con LINQ
Contenido del curso
Mairon Andres Florez Alvarez
Mairon Andres Florez Alvarez
Jimmy Buriticá Londoño
Laura Valentina Bernate Gordillo
Luca Cristian Manea
Sandra Valentina Rodríguez Cortés
Joan Alexander Valerio Rodríguez
Federico Mikolajewski
JOHN CARLOS ARRIETA ARRIETA
Miguel Teheran
kolab Linkear
Jonathan Harley Sabogal toro
Betzabhe Elizabeth Vega Aliaga
Mario Andrés Orozco Sánchez
Miguel Angel Reyes Moreno
Carlos Arturo Pimentel
Les comparto mi funcion generica que aprovecha el uso de funciones anonimas como parametros para filtrar, ordenar y seleccionar los datos dandole dinamismo a la implementacion. considere _librosLt como el listado de libros disponibles para consultar
public IEnumerable<dynamic> GetCustomBook( Func<Book, dynamic> select, Func<Book, bool> where, Func<Book, object> order, int take, int skip = 0) { return this._librosLt .Where(where) .OrderBy(order) .Take(take) .Select(select); }
Y asi seria su invocacion
LinqQueries queries = new LinqQueries(); var selectCustom = queries.GetCustomBook(select: x => new Book { Title = x.Title, PageCount = x.PageCount }, where: x => x.PageCount > 400, order: x => x.PublishedDate, take: 4, skip: 0); foreach (var i in selectCustom) Console.WriteLine(string.Format("{0, -60} {1, 15}\n", i.Title, i.PageCount));
Operador Select
Nos permite seleccionar campos específicos de un objeto, para mejorar el rendimiento y ahorrar espacio en memoria.
me demoré como 2h pero pude con el reto ajajajaja
public List<Book> getTop3FromBooks(IEnumerable<Book> books){ return books.Take(3).Select(p=> new Book(){Title = p.Title, PageCount = p.PageCount}).ToList(); }
public class BookDTO{ public string Title {get;set;} public int PageCount {get;set;} } public List<BookDTO> getTop3FromBooksQuery(IEnumerable<Book> books){ return (from b in books select new BookDTO{Title = b.Title, PageCount=b.PageCount}).Take(3).ToList(); }
public class Item { public string Title { get; set; } public int PageCount { get; set; } } public IEnumerable<Item> seleccionarTituloYNumPagDeLosPrimerosTresLibros() { return booksCollection.Take(3).Select(x=> new Item() {Title =x.Title, PageCount=x.PageCount}); }
A continuación les comparto lo practicado en este clase, utilizando Extension method y query expression. También quise agregar un ejercicio con un mayor nivel de dificultad, tomándo en cuenta clases pasadas.
//Extension Method return BooksCollections .Take(3) .Select(p => new Book { Title = p.Title, PageCount = p.PageCount }); //Query expression var query = (from p in BooksCollections select new Book { Title = p.Title, PageCount = p.PageCount }) .Take(3); return query; //Mi reto var query = (from p in BooksCollections where p.Title.Contains("Java") select new Book { Title = p.Title, PublishedDate = p.PublishedDate}) .Take(2); return query; ```Espero les ayude :D
public IEnumerable<Book> TresPrimerosLibros() { return librosCollection.Take(3) .Select(p=> new Book() { Title = p.Title, PCount = p.PageCount }) }
Saludos Miguel.
Gracias por el contenido de formación, es excelente .
Esta técnica de Linq nos facilita un poco parte del trabajo de obtener los objetos DTO a nivel de vista (ViewObject) a partir de de los objetos de Dominio, por ejemplo (los Entity) y evitar usar librerías de terceros como por ejemplo AutoMapper
Aprovecho la oportunidad para saber tu opción de un tema relacionado con DTO.
Siguiendo las recomendaciones de DDD y Arquitectura limpia, y tonando como base la clase Book de tu ejemplo, imaginemos que esta clase representa una entidad de negocio, entonces, el lugar ideal seria colocarla en la capa de Dominio o ``` namespace Xyx.Domain.Entityes
++LA PREGUNTA ES:++ **¿Dónde colocarías las clases DTO **BookRequesty** **BookResponse**? OPCIONES DE REPSUESTA: En la **capa transversal** o común:
En la **capa de Infraestructura**:
En la **capa de Dominio**:
Ojala pueda contar con tu respuesta, así tendré otra perspectiva sobre este dilema y tomar la decisión correcta. El problema esta en que estas clases por su definición, forma y uso pueden ser candidatas a formar parte de cualquiera de esas tres capas, por su puesto, la capa de Servicio esta excluida como alternativa. Quedo atento. Muchas gracias por tu aportes.
Si la idea es crear un model para transferir datos entre las capas entonces deberia ir la capa de domain o dominio
Les propongo esta solución:
Creamos una nueva clase con los datos necesarios:
Creamos la Query:
Y Mandamos a llamar:
public IEnumerable<Book> TresPrimeroLibrosDeLaColeccion() { return booksCollection.Take(3) .Select(p => new Item(p.Title, p.PageCount) { Title = p.Title, PageCount = p.PageCount}); } ``` public IEnumerable\<Book> TresPrimeroLibrosDeLaColeccion() { return booksCollection.Take(3) .Select(p => new Item(p.Title, p.PageCount) { Title = p.Title, PageCount = p.PageCount}); }
public IEnumerable<object> TituloNumeroPagdeTresPrimerosLibros() { var libros = librosCollection .OrderByDescending(p => p.PageCount) .Take(3) .Select(p => new { Title = p.Title, Paginas= p.PageCount }); foreach (var libro in libros) { Console.WriteLine($"Título: {libro.Title}, Fecha de Publicación: {libro.Paginas}"); } return libros ; }
public IEnumerable<Book> TresPrimerosLibros() { return (from l in librosColletion select new Book{ Title = l.Title , PageCount= l.PageCount}).Take(3) ; }
Lo conseguí!:
Item.cs:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Curso_Linq { internal class Item { public string? Title { get; set; } public int PageCount { get; set; } } }
al final del LinqQueries.cs:
internal class LinqQueriesItems { private List<Item> items = new List<Item>(); public LinqQueriesItems() { using (StreamReader reader = new StreamReader("books.json")) { string json = reader.ReadToEnd(); this.items = System.Text.Json.JsonSerializer.Deserialize<List<Item>>(json, new System.Text.Json.JsonSerializerOptions() { PropertyNameCaseInsensitive = true }); } } public IEnumerable<Item> PrimerosXLibros(int quantity) { return items.Take(quantity) .Select(book => new Item() { Title = book.Title, PageCount = book.PageCount }); } }
en Program.cs:
LinqQueriesItems items = new(); string formatoTextoItem = "{0, -60} {1, 15}"; void ImprimirItems(IEnumerable<Item> listaDeItems) { Console.WriteLine($"{formatoTextoItem}\n", "Titulo", "N. Paginas"); foreach (var book in listaDeItems) { Console.WriteLine($"{formatoTextoItem}", book.Title, book.PageCount); } } //* Primeros X libros filtadros con Select ImprimirItems(items.PrimerosXLibros(3));
Esta parece una excelente oportunidad para aplicar el patrón creacional Builder