martes, 26 de febrero de 2019
Sin duda, Entity Framework Core es un gran marco de trabajo para implementar el acceso a datos de nuestras aplicaciones, pues es rápido, potente y nos ahorra una gran cantidad de esfuerzo, sobre todo en proyectos muy centrados en datos.
Sin embargo, estas ayudas tienen un coste importante, al igual que ocurre con casi cualquier framework al que vayamos a confiar parte de nuestro sistema, sea del ámbito que sea: hay que conocerlo bien para no dispararse en un pie en cuanto apretemos el gatillo.
Hace muuuuchos, muchos años hablamos de cómo aplicar convenientemente la carga anticipada (eager loading) en Entity Framework podía acelerar de forma drástica el rendimiento en el acceso a datos de nuestras aplicaciones, evitando el temido problema denominado "SELECT N+1". Esto continúa siendo válido para la versión Core de este marco de trabajo: sigue existiendo el extensor
Pues bien, en EF Core hay otro detalle que, si bien utilizándolo con conocimiento puede resultar muy interesante, es fácil que nos tumbe el rendimiento de nuestros accesos a datos si no lo usamos con cuidado: la evaluación en cliente.
Sin embargo, estas ayudas tienen un coste importante, al igual que ocurre con casi cualquier framework al que vayamos a confiar parte de nuestro sistema, sea del ámbito que sea: hay que conocerlo bien para no dispararse en un pie en cuanto apretemos el gatillo.
Hace muuuuchos, muchos años hablamos de cómo aplicar convenientemente la carga anticipada (eager loading) en Entity Framework podía acelerar de forma drástica el rendimiento en el acceso a datos de nuestras aplicaciones, evitando el temido problema denominado "SELECT N+1". Esto continúa siendo válido para la versión Core de este marco de trabajo: sigue existiendo el extensor
Include()
e incluso variantes de éste como ThenInclude()
que permiten incluir en una única consulta las entidades que sabemos que vamos a necesitar.Pues bien, en EF Core hay otro detalle que, si bien utilizándolo con conocimiento puede resultar muy interesante, es fácil que nos tumbe el rendimiento de nuestros accesos a datos si no lo usamos con cuidado: la evaluación en cliente.
lunes, 25 de febrero de 2019
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Expresiones lambda como delegados
José María Aguilar - Capturar la pantalla con Windows 10
José María Aguilar
.NET / .NET Core
- .NET Core 1.0 and 1.1 will reach End of Life on June 27, 2019
Rich Lander - Announcing .NET Framework 4.8 Early Access Build 3745
Namrata Karnam - C# 8 – Introducing Index struct and a brand new usage for the hat operator – Developers Anonymous
John Demetriou - Dynamically compile and run code using .NET Core 3.0
Laurent Kempé - Novedades de C# 8
Fernando Escolar - Novedades de C# 8.0 al escenario
David Gonzalo - Universal hierarchy traversing in C#
Gunnar Peipman - Switching Between .NET Core SDK Versions
Faisal Pathan - Introduction to Benchmarking C# Code with Benchmark .NET
Steve Gordon - .NET Internals Cookbook Part 1 — Exceptions, filters and corrupted processes
Adam Furmanek - C# 8: Default Interface Methods Implementation
Dawid Sibiński - How to exclude code from code coverage
Gunnar Peipman - Heap vs stack, value type vs reference type
Konrad Kokosa - HttpClient Creation and Disposal Internals: Should I Dispose of HttpClient?
Steve Gordon - What's the Difference Between Razor and Blazor?!?
Jason Robert - Dependency Injection for Quartz.NET in .NET Core
Bohdan Stupak - Exploring .NET Core 3.0 new API
Patrick Smacchia
martes, 19 de febrero de 2019
Una gestión apropiada de la caché es muchas veces el secreto para los sistemas de alto rendimiento o que tienen que atender a una gran carga de peticiones por segundo, y el framework ASP.NET Core MVC incluye numerosas herramientas para ello.
Entre otras, el tag helper
Si volvemos a acceder a la misma vista durante esos 30 segundos, el resultado será mostrado inmediatamente (sin esperar los tres segundos) y el cliente recibirá el contenido que se cacheó durante la primera visita. Al transcurrir este plazo, en la siguiente petición se volverá a procesar el contenido del tag helper, ejecutándose la espera y volviendo a generar y cachear el resultado enviado al cliente.
Pero podemos tener ejemplos algo más complejos, como el siguiente. En el interior del tag helper hemos insertado un view component que podría mostrar las últimas noticias obtenidas de una base de datos, en lo que podría ser la página de inicio de un servicio de información on-line:
Entre otras, el tag helper
<cache>
es especialmente útil para almacenar en la memoria del servidor el resultado de procesar una porción de página o vista, de forma que pueda ser reutilizada en peticiones siguientes. Un ejemplo bastante básico, pero que deja bastante clara su utilidad y forma de uso, podría ser el siguiente:<h1>Atomic clock</h1>
<cache expires-after="@TimeSpan.FromSeconds(30)">
@{
await Task.Delay(3000);
}
Current time: @DateTime.UtcNow.ToLongTimeString()
</cache>
Al acceder a una vista con el código anterior por primera vez, se producirá un retardo forzado de tres segundos, se renderizará el interior del tag <cache>
mostrando la hora actual, y el resultado será almacenado en memoria durante 30 segundos.Si volvemos a acceder a la misma vista durante esos 30 segundos, el resultado será mostrado inmediatamente (sin esperar los tres segundos) y el cliente recibirá el contenido que se cacheó durante la primera visita. Al transcurrir este plazo, en la siguiente petición se volverá a procesar el contenido del tag helper, ejecutándose la espera y volviendo a generar y cachear el resultado enviado al cliente.
Pero podemos tener ejemplos algo más complejos, como el siguiente. En el interior del tag helper hemos insertado un view component que podría mostrar las últimas noticias obtenidas de una base de datos, en lo que podría ser la página de inicio de un servicio de información on-line:
<section>
<h1>Latest news</h1>
<cache expires-after="@TimeSpan.FromSeconds(30)">
<vc:latest-news></vc:latest-news>
<p>
Updated at: @DateTime.UtcNow.ToLongTimeString()
</p>
</cache>
</section>
Fijaos que en este caso el tiempo de invalidación del contenido almacenado en caché no tendría sentido que fuera periódico: ¿para qué invalidar la caché y volver a obtener las noticias de la base de datos cada X segundos si quizás no se ha introducido ninguna nueva desde la última vez que se renderizó la página? ¿No sería mejor recargar la caché sólo cuando se hayan modificado las noticias?
lunes, 18 de febrero de 2019
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Usar Razor desde una aplicación de consola .NET Core (1 de 2)
José María Aguilar - C#: Desmitificando las expresiones lambda (I)
José María Aguilar
.NET / .NET Core
- Adapting Projects to Use C# 8 and Nullable Reference Types
Jonathan Allen - NullableAttribute and C# 8
Jon Skeet - Instantiating a C# object from a string using Activator.CreateInstance in .NET
Jeremy Lindsay - Asynchronous Injection
Mark Seemann - Automating .NET Core Services with PostSharp and Aspect-Oriented Code
Alexander Johnston - Readonly ref variables, in parameters and readonly structs
Konrad Kokosa - Size of struct and size of class in .NET
Jiří Činčura - Using declarations in C# 8.0
Gunnar Peipman - Hunting .NET memory leaks with Windbg
André Snede Kock - An Exhausting List of Differences Between VB.NET & C#
Anthony D. Green - Simple Transaction: Microservices sample architecture for .Net Core Application
John-Ph - VB.NET Popularity Still Rising
David Ramel - When to use C# LINQ with Query Syntax over Method Syntax
Michael Shpilt - C# 8: slicing with Indexes and Ranges
Dawid Sibiński - How many keywords I can fit into a single C# expression? – results
Jiří Činčura - Dependency injection in .NET Core console applications
Gunnar Peipman
martes, 12 de febrero de 2019
Como sabemos, ASP.NET Core incluye un sistema de inyección de dependencias que, aunque es algo simple comparado con otras alternativas más veteranas, cubre la mayoría de necesidades habituales. Por ejemplo, un aspecto que no es muy conocido y que puede ser útil en muchas ocasiones es su capacidad para registrar y recuperar múltiples implementaciones de una misma interfaz.
En este post vamos a ver cómo conseguirlo, y un caso práctico de uso de esta técnica en un escenario muy frecuente.
En este post vamos a ver cómo conseguirlo, y un caso práctico de uso de esta técnica en un escenario muy frecuente.
Publicado por José M. Aguilar a las 8:30 a. m.
Etiquetas: aspnetcore, aspnetcoremvc, patrones, trucos
lunes, 11 de febrero de 2019
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- 101 formas de saber que tu proyecto está condenado al fracaso
José María Aguilar - Generar redirecciones HTTP 307 y 308 en ASP.NET Core MVC
José María Aguilar
.NET / .NET Core
-
Historia de C#
Fernando Escolar - AppSettings.json, an unfortunate name?
Daniel Wertheim - Advanced C# - Dynamic Type
Marinko Spasojevic - C# 8 is fixing interpolated verbatim strings – Developers Anonymous
John Demetriou - An extension method for .NET enumerations that uses the DescriptionAttribute
Jeremy Lindsay - Fixing Random, part 2
Eric Lippert - Working with types in a Roslyn analyzer
Gérald Barré - C# 8: Nullable Reference Types
Dawid Sibiński - C# Futures: Lambda Attributes & Static Delegates and Function Pointers
Jonathan Allen - How many keywords I can fit into a single C# expression?
Jiří Činčura - New Jasper Alpha for HTTP Services
Jeremy D. Miller - Brainstorming - Creating a small single self-contained executable out of a .NET Core application
Scott Hanselman - How to debug .NET Deadlocks (C# Deadlocks in Depth - Part 3)
Michael Shpilt - Cómo guardar "secretos" en nuestras aplicaciones de .NET Core (sin peligro de enviarlos a GitHub por error)
Jorge Turrado
martes, 5 de febrero de 2019
Tradicionalmente los middlewares de ASP.NET Core los hemos implementado como clases independientes
más o menos con la siguiente pinta:
La ausencia de interfaces o clases base aporta flexibilidad, pero elimina las ayudas propias del tipado fuerte y puede ser fuente de problemas si no atendemos a estas convenciones con cuidado. Es decir, si en lugar del método
También es importante tener en cuenta que una clase middleware sólo es instanciada una vez, cuando la aplicación está arrancando; luego, en cada petición será ejecutado su método
public class MyCustomMiddleware
{
private readonly RequestDelegate _next;
public MyCustomMiddleware(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
// Hacer algo antes de pasar el control al siguiente middleware
await _next(context); // Pasar el control al siguiente middleware
// Hacer algo después de ejecutar el siguiente middleware
}
}
Estas clases no heredan de ninguna otra ni implementan interfaces proporcionadas por el framework, aunque atienden a convenciones simples, como la recepción en el constructor del delegado al siguiente middleware en el pipeline, o la existencia de un método Invoke()
o InvokeAsync()
, que es donde introduciremos nuestra lógica, recibiendo el contexto HTTP.La ausencia de interfaces o clases base aporta flexibilidad, pero elimina las ayudas propias del tipado fuerte y puede ser fuente de problemas si no atendemos a estas convenciones con cuidado. Es decir, si en lugar del método
Invoke()
por error escribimos Invke()
, nada fallará en compilación. Tendremos que esperar a ejecutar la aplicación para que explote.También es importante tener en cuenta que una clase middleware sólo es instanciada una vez, cuando la aplicación está arrancando; luego, en cada petición será ejecutado su método
Invoke()
sobre la misma instancia, lo que es a priori muy poco intuitivo y puede causarnos algún dolor de cabeza si no somos cuidadosos.
lunes, 4 de febrero de 2019
Ahí van los enlaces recopilados durante la semana pasada. Espero que os resulten interesantes. :-)
Por si te lo perdiste...
- Programadores con producción neta negativa (NNPP)
José María Aguilar - ¿Aún usas ToString() para obtener el nombre de los elementos de un enum?
José María Aguilar
.NET / .NET Core
- Announcing .NET Core 3 Preview 2
Rich Lander - Introducing the .NET Community Standup Series
James Montemagno - Generate disassembly of .NET functions
Wojciech Nagórski - Tic Tac Toe Using AI –The Easy Way
George Swan - Designing Data Objects in C#: More examples
Yacoub Massad - yield return await and await foreach geekery
Jiří Činčura - C# 8 using declarations
Kevin Jones - C# Interface: Definition, Examples, Best Practices, and Pitfalls
Phil Vuollet - System.Collections in .NET Core 3.0
Jonathan Allen - WTF Is a Lambda
Jon Hilton - [C#] Have some fun with .net core startup hooks
Kévin Gosse - Dependency Hell
Damian Laczak - Is WPF Still Relevant in 2019?
Claudio Bernasconi - Update on IAsyncDisposable and IAsyncEnumerator
Jonathan Allen - Fixing random, part 1
Eric Lippert