<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Eduardo Barrios</title>
    <description>The latest articles on Forem by Eduardo Barrios (@ebarrioscode).</description>
    <link>https://forem.com/ebarrioscode</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F266312%2F64e4f515-0a74-4eb0-8ac4-76678329e64e.jpg</url>
      <title>Forem: Eduardo Barrios</title>
      <link>https://forem.com/ebarrioscode</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/ebarrioscode"/>
    <language>en</language>
    <item>
      <title>Ingeniería de Software - Test Unitarios. Cómo tratar dependencias de BD con Base de Datos en memoria y Entity Framework Core</title>
      <dc:creator>Eduardo Barrios</dc:creator>
      <pubDate>Tue, 24 Aug 2021 02:17:40 +0000</pubDate>
      <link>https://forem.com/ebarrioscode/ingenieria-de-software-test-unitarios-como-tratar-dependencias-de-bd-con-base-de-datos-en-memoria-y-entity-framework-core-2318</link>
      <guid>https://forem.com/ebarrioscode/ingenieria-de-software-test-unitarios-como-tratar-dependencias-de-bd-con-base-de-datos-en-memoria-y-entity-framework-core-2318</guid>
      <description>&lt;p&gt;Comúnmente en ingeniería de software es necesario escribir código que comprueba la correcta funcionalidad de ciertos componentes de nuestros sistemas, obviamente estos deben poseer una arquitectura limpia o cualquier arquitectura de software definida bajo buenas prácticas y patrones de diseño que a su vez nos permitan probar de manera aislada cada parte de nuestro código.&lt;br&gt;
Las dependencias son un tema inevitable dentro del software, estás pueden ser llamadas a una base de datos, peticiones mediante un cliente Soap o Rest, llamadas a cualquier servicio externo o recurso de Azure, etc. Pero en la etapa que concierne a las pruebas unitarias no necesitamos utilizar las dependencias reales para probar la funcionalidad y asegurar la calidad de nuestro código, es decir no necesito conectarme a la base de datos real de producción, pre-producción, qa, o desarrollo para probar que en verdad mi código inserta en la base de datos, o no necesito realmente conectarme a Azure a un servicio real como el de Azure Cosmos DB para probar las funcionalidades que existen dentro de mi código que utilizan ese servicio de Azure.&lt;br&gt;
Para resolver este problema en esta fase del desarrollo de software recurrimos a utilizar Mocks, concepto que hace referencia a utilizar implementaciones fake que permiten simular cada uno de los diferentes casos o variaciones de comportamiento que podría ocurrir como resultado en nuestro código.&lt;br&gt;
En este post abordaremos pruebas unitarias con el proveedor de base de datos en memoria de Entity Framework Core para tratar con una de las dependencias existentes en un proyecto que desarrolle hace algunos meses en .NET 5 (WebApi y Blazor WASM), consiste en un proyecto API con su respectiva aplicación SPA que expone información de paises y sus códigos, además está definido bajo una arquitectura limpia y buenas prácticas de código limpio y patrones de diseño.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fef19a24o16phvq5gnz5k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fef19a24o16phvq5gnz5k.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inicialmente necesitaremos tener un proyecto de Pruebas dentro de nuestra solución, personalmente me gusta utilizar un proyecto de pruebas de xUnit.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm2r2e73ujo2aemlqzk7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftm2r2e73ujo2aemlqzk7.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Después de crear nuestro proyecto de pruebas necesitaremos instalar el paquete Nuget Microsoft.EntityFrameworkCore.InMemory&lt;br&gt;
utilizando la consola de administración de paquetes de Visual Studio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Install-Package Microsoft.EntityFrameworkCore.InMemory -Version 5.0.9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Dentro de la estructura del proyecto existe una capa llamada Infrastructure la cuál contiene el contexto de datos real de Entity Framework Core que se conecta a la base de datos, también  contiene las migraciones a la base de datos, una definición de Repositorio Genérico y del patrón Unit Of Work para gestionar las operaciones de una manera centralizada hacía la base de datos. Dentro del directorio Repositories existe una implementación custom para cada objeto representado con base en una tabla de base de datos, lo que queremos en este post es poder probar la funcionalidad de los repositories de manera aislada en nuestro proyecto de pruebas, todo esto sin tener que conectarnos a la base de datos real.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F53w1g00wog651lldmjer.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F53w1g00wog651lldmjer.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xe3szmplr0o4n7g8au6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xe3szmplr0o4n7g8au6.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  OK!
&lt;/h2&gt;

&lt;p&gt;Vamos al código.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Necesitaremos crear un contexto de Entity Framework Core el cuál utilizaremos para pasarlo como parámetro a nuestra implementación fake de UnitOfWork, para esto crearemos un directorio llamado ResourcesDatabase en la raíz del proyecto de pruebas y seguidamente crearemos una clase llamada BaseContextTest.cs. Añadiremos el siguiente código.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsa34qz9cppjuclscdgn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffsa34qz9cppjuclscdgn.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; en la clase BaseContextTest es necesario configurar el tipo de base de datos, en este caso en memoria, para luego pasar esa configuración a una instancia de nuestro contexto real que es el que necesitamos burlar para poder probar la funcionalidad del repository.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;También crearemos una clase para inicializar nuestra base de datos en memoria.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffp5hpjp7tmxvhb55oubc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffp5hpjp7tmxvhb55oubc.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Luego de preparar una implementación fake para probar la funcionalidad del repository procedemos a crear una clase llamada CountriesRepositoryTest.cs dentro de la ruta Infrastructure.Repositories.Tests/Countries y dentro de está clase podremos crear pruebas unitarias que hagan referencia a los diferentes casos de comportamiento que puedan ocurrir en el código del repository. Probaremos el caso en el que nuestro repository devuelve una lista de elementos de una tabla de la base de datos, para esto crearemos un método que haga referencia a esa prueba.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjo9iq74fmrd1v5qjy1rq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjo9iq74fmrd1v5qjy1rq.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;En este test cumplimos con uno de los fundamentos de los test unitarios, el patrón de las 3 A´s el cuál se organiza de la siguiente manera:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Arrange&lt;/strong&gt; (Organizar/Inicializar) =&amp;gt; Inicializa los objetos y establece los valores de los datos que vamos a utilizar en el Test que lo contiene, en nuestro test creamos e inicializamos un objeto que implemente la interface IUnitOfWork haciendo uso de la librería Moq, en la siguiente línea pasamos el contexto propio del proyecto de pruebas unitarias a nuestro objeto fake de UnitOfWork ya que este será necesario para mandárselo al método constructor de la instancia de CountriesRepository, está es la clase a la cuál queremos probar su funcionalidad.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Act&lt;/strong&gt; (Actuar) =&amp;gt; realiza la llamada al método a probar con los parámetros preparados para tal fin, en nuestro test creamos una instancia de CountriesRepository (clase que queremos probar) pasamos el objeto fake creado en el Arrange y luego invocamos al método del repository que queremos probar.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Assert&lt;/strong&gt; (Confirmar/Comprobar) =&amp;gt; comprueba que el método de pruebas ejecutado se comporta tal y como teníamos previsto que lo hiciera, en nuestro test a manera de ejemplo y aprendizaje hacemos varias aserciones aunque no es lo recomendado.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Consejo de Expertos:&lt;/strong&gt; Al escribir test unitarios, incluye solo una aserción por prueba, ya que si agregas varias aserciones en un caso de prueba, no se garantiza que se ejecuten todas. En la mayoría de los marcos de trabajo de pruebas unitarias, cuando se produce un error en una aserción de un test unitario, las aserciones siguientes se consideran fallidas automáticamente. Esto puede ser confuso, ya que la funcionalidad en componentes que realmente son correctas, se muestran fallidas.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Procedemos a ejecutar nuestro unit test recién creado y podremos comprobar que el test pasa correctamente.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc52g5jhpvt8gwadtsusp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc52g5jhpvt8gwadtsusp.png" alt="image"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Conclusiones:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Utilizar una librería de Mocks es bastante útil en el testing de código, ya que nos evita estar creando clases para abarcar cada uno de los comportamientos o resultados que pueda tomar nuestro código y que necesitamos probar.&lt;/li&gt;
&lt;li&gt;En este post vimos una de las utilidades de las bases de datos en memoria aplicada al testing de código y la facilidad con la que podemos mockear un contexto de base de datos sin necesidad de conectarnos a la base de datos real para probar la funcionalidad del acceso a datos y demás operaciones involucradas.&lt;/li&gt;
&lt;li&gt;La técnica de mock de dependencias en test unitarios es una técnica profesional, avanzada y muy utilizada que existe en la ingeniería de software para escribir test unitarios cortos y precisos y poder probar componentes que están correctamente desacoplados.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link al respositorio en GitHub&lt;/strong&gt;&lt;br&gt;
 &lt;a href="https://github.com/EbarriosCode/BackendDotnet_CleanArchitecture/tree/master" rel="noopener noreferrer"&gt;https://github.com/EbarriosCode/BackendDotnet_CleanArchitecture/tree/master&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Referencias&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/es-es/dotnet/core/testing/unit-testing-best-practices" rel="noopener noreferrer"&gt;https://docs.microsoft.com/es-es/dotnet/core/testing/unit-testing-best-practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/ef/core/providers/in-memory/?tabs=dotnet-core-cli" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/ef/core/providers/in-memory/?tabs=dotnet-core-cli&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.c-sharpcorner.com/uploadfile/john_charles/mocking-in-net-with-moq/" rel="noopener noreferrer"&gt;https://www.c-sharpcorner.com/uploadfile/john_charles/mocking-in-net-with-moq/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>testing</category>
      <category>csharp</category>
      <category>dotnet</category>
      <category>database</category>
    </item>
    <item>
      <title>Píldoras de C#: Task Parallel Library (TPL) Procesamiento Multihilo y asíncrono</title>
      <dc:creator>Eduardo Barrios</dc:creator>
      <pubDate>Sun, 20 Dec 2020 16:51:04 +0000</pubDate>
      <link>https://forem.com/ebarrioscode/pildoras-de-c-task-parallel-library-tpl-procesamiento-multihilo-y-asincrono-18mp</link>
      <guid>https://forem.com/ebarrioscode/pildoras-de-c-task-parallel-library-tpl-procesamiento-multihilo-y-asincrono-18mp</guid>
      <description>&lt;p&gt;Esta publicación, forma parte del &lt;a href="https://aspnetcoremaster.com/calendario-adviento-csharp-2020.html"&gt;3er. Calendario Adviento C# 2020,&lt;/a&gt; una iniciativa liderada por Benjamín Camacho. &lt;/p&gt;

&lt;p&gt;A continuación les traigo mi aporte sencillo pero no menos importante en el desarrollo de software y el uso de características geniales del lenguaje de programación C# en este caso el procesamiento multithreading y asíncrono mediante TPL.&lt;/p&gt;

&lt;p&gt;Para comprender TPL es necesario comprender algunos fundamentos respecto a como funcionan los hilos, el grupo de hilos, características del sistema operativo como el scheduler, procesos, registros, etc.&lt;/p&gt;

&lt;p&gt;Es lógico pensar que a medida que las aplicaciones se vuelven indispensables en cualquier entorno también se vuelven más complejas y las expectativas del usuario aumentan, ante esta problemática los desarrolladores de software podemos tomar ventaja de sistemas multinúcleo y capacidades de respuesta optimas para crear aplicaciones que utilicen múltiples threads (hilos) y lograr el famoso paralelismo. Antiguamente las computadoras arquitectónicamente hablando fueron creadas siguiendo el diseño lógico denominado Arquitectura de Von Newmann, la cual contaba con una unidad de procesamiento, una unidad de control, entrada y salida, y la unidad de procesamiento y control formaban la unidad de procesamiento central CPU, pero este diseño contaba con una sola unidad de procesamiento por lo que los programas debían ser escritos para funcionar bajo este diseño y eso implicaba escribir código que se ejecutara de manera secuencial.&lt;/p&gt;

&lt;p&gt;Con base en el anterior fundamento pensemos en la siguiente premisa, una computadora con una sola CPU es capaz de ejecutar una sola operación a la vez, pero que sucede si esa operación es muy trabajosa y lleva mucho tiempo de ejecución para esa CPU. Mientras se ejecuta ese proceso las demás operaciones quedarían en pausa, obviamente esto significa que toda la computadora se congelaría y no respondería aparentemente, y todo empeoraría más sí ese proceso contiene un error por lo que la computadora quedaría inutilizable y lo único que puedes hacer es reiniciar. Para solucionar esto se utiliza el concepto de Thread (Hilo).&lt;/p&gt;

&lt;h1&gt;
  
  
  Entendiendo los Threads
&lt;/h1&gt;

&lt;p&gt;En las versiones actuales del Sistema Operativo Windows, cada aplicación se ejecuta en su propio proceso, un proceso se encarga de separar aplicaciones de otras aplicaciones asignándoles su propia memoria virtual y asegurado que los diferentes procesos no puedan interferir entre sí, cada proceso se ejecuta en su propio hilo. Un Thread (Hilo) es algo así como una CPU virtualizada que permite a una aplicación realizar varias tareas a la vez en paralelo, es parecido al concepto multitarea a nivel del sistema operativo pero los Threads se enfocan en subprocesos que pertenecen a un mismo proceso y la diferencia es que los Threads comparten espacio de memoria y los procesos no.&lt;br&gt;
Para el caso del Sistema Operativo Windows, este administra todos los subprocesos para garantizar que puedan ejecutarse y realizar su trabajo, el SO se encarga de esa administración, de darle tiempo de ejecución en la CPU y cuando este tiempo de ejecución termina, el subproceso se detiene y Windows cambia a otro Thread, esto es a lo que se le conoce como cambio de contexto.&lt;br&gt;
Para poder utilizar Threads en nuestras apliaciones .NET podemos recurrir al espacio de nombres System.Threading en donde encontraremos la clase Thread con la que podremos crear nuevos Threads, gestionar su prioridad y obtener su estado.&lt;br&gt;
Veamos un ejemplo con código C# de como podemos ejecutar un segundo Thread al tiempo que realizamos una operación en el Thread principal de una aplicación de consola.&lt;br&gt;
Crearemos 3 métodos &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;ReadDataFromIO&lt;/strong&gt; =&amp;gt; este método simula lectura y escritura de archivos, aunque en realidad lo que hacemos es poner el hilo actual en suspensión para simular esa operación de IO.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;ReadDataFromIO&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// Estamos simulando una E/S poniendo el hilo actual en suspensión.&lt;/span&gt;
   &lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;10d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;DoIntensiveCalculations&lt;/strong&gt; =&amp;gt; este método simula cálculos matemáticos intensivos, aunque en realidad lo que haremos será hacer divisiones sin sentido solo para efectos de simulación.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="nf"&gt;DoIntensiveCalculations&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// Estamos simulando cálculos intensivos&lt;/span&gt;
   &lt;span class="c1"&gt;// haciendo divisiones sin sentido&lt;/span&gt;
   &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;100000000d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;maxValue&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Int32&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MaxValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;maxValue&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;/=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;RunWithThreads&lt;/strong&gt; =&amp;gt; este método contendrá la ejecución de ambas operaciones y será invocado en el método main de la clase Program.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;RunWithThreads&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="c1"&gt;// Crear el hilo para leer desde E/S&lt;/span&gt;
   &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;thread&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;ReadDataFromIO&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

   &lt;span class="c1"&gt;// Iniciar el hilo&lt;/span&gt;
   &lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Start&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

   &lt;span class="c1"&gt;// Guardar el resultado de el calculo en otra variable&lt;/span&gt;
   &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;result2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;DoIntensiveCalculations&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

   &lt;span class="c1"&gt;// Esperar a que el hilo termine &lt;/span&gt;
   &lt;span class="n"&gt;thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Join&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

   &lt;span class="c1"&gt;// Calcular el resultado final&lt;/span&gt;
   &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;result2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="c1"&gt;// Imprimir el resultado&lt;/span&gt;
   &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"El resultado es {0}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ahora en el método Main invocaremos RunWithThreads().&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;RunWithThreads&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Independientemente del resultado podemos ver que ambos hilos se ejecutan, inicialmente pasamos un delegado como parámetro en el método constructor de la instancia de la clase Thread, el hilo no se inicia cuando se crea, debemos iniciarlo llamando al método Start(), esto pone en cola este nuevo hilo para su ejecución mientras continúa ejecutando el código en el método actual, seguidamente al ejecutar el método DoIntensiveCalculations se realiza el cálculo intensivo y debe esperar a que el hilo creado anteriormente termine de ejecutarse, esto sucede al invocar al método Join, thread.Join bloquea el hilo actual hasta que el otro hilo termine de ejecutarse y cuando finalice el otro hilo, Join volverá y el hilo actual se desbloqueará. A grandes rasgos de esta manera podemos gestionar los Threads en C#.&lt;/p&gt;

&lt;h1&gt;
  
  
  Entendiendo el Thread Pool (Grupo de Hilos)
&lt;/h1&gt;

&lt;p&gt;Cuando trabajamos directamente con la clase Thread, creamos un nuevo hilo cada vez y ese hilo que creamos cuando termina su ejecución este muere al finalizar, no obstante esto para el manejador de procesos del sistema operativo representa un golpe al rendimiento al costarle algo de tiempo y recursos. Afortunadamente en C# tenemos la clase static ThreadPool que representa un grupo de hilos que nos permite reutilizar hilos, en lugar de dejar morir un hilo cuando finalice su ejecución se envía de vuelta al Thread Pool donde puede estar para ser reutilizado cada vez que llega una petición. Para utilizarla lo único que debemos hacer es pasar nuestra operación al método QueueUserWorkItem que se encargará de colocar el elemento recibido en una cola administrada por el Thread Pool para que cuando un Thread del Thread Pool este disponible este recogerá el elemento y lo ejecutará hasta su finalización, aunque tenemos un problema debido a que no se sabe cuando el subproceso terminará su trabajo y no hay ningún tipo de Join para bloquear y forzar una espera. Para resolver esto debemos recurrir a la sincronización de recursos pero es algo que no veremos en este Post y debido a que no se recomienda ni tampoco utilizaremos la clase ThreadPool a menudo ya que en su lugar se debe utilizar otras tecnologías como el Task Parallel Library (TPL) que veremos más adelante.&lt;br&gt;
Veamos el ejemplo anterior con código C# pero esta vez utilizando la clase ThreadPool.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;RunInThreadPool&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="c1"&gt;// Crear un elemento de trabajo para leer desde E/S&lt;/span&gt;
   &lt;span class="n"&gt;ThreadPool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;QueueUserWorkItem&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="nf"&gt;ReadDataFromIO&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;

   &lt;span class="c1"&gt;// Guardar el resultado del calculo en otra variable&lt;/span&gt;
   &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;result2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;DoIntensiveCalculations&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="c1"&gt;// Esperar a que el Thread termine&lt;/span&gt;

   &lt;span class="c1"&gt;// HACER: Necesitaremos una manera de indicar &lt;/span&gt;
   &lt;span class="c1"&gt;// cuando el Thread del ThreadPool finalizó la ejecución&lt;/span&gt;

   &lt;span class="c1"&gt;// Calcular el resultado final&lt;/span&gt;
   &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;result2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"El resultado es {0}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora en el método Main invocaremos RunInThreadPool().&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;RunInThreadPool&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Independientemente del resultado de esta manera utilizamos el ThreadPool que viene siendo como una versión 2 de los Hilos.&lt;br&gt;
Algo que debemos saber del Thead Pool es que este limita el número disponible de Threads, esto significa que obtendremos un grado menor de paralelismo que usando la clase Thread a secas. Pero el Thread Pool también tiene muchas ventajas por ejemplo pensemos en un servidor web que atiende peticiones entrantes. Todas esas peticiones llegan en un tiempo y frecuencia que no conocemos. El Thread Pool garantiza que cada petición se agregue a una cola y que cuando exista un Thread disponible este procese la petición. Esto nos asegura que el servidor no se no bloqueará por la cantidad de solicitudes, en cambio si usamos la clase Thread y gestionamos los hilos manualmente podemos derribarlo fácilmente si este recibiera infinidad de peticiones.&lt;/p&gt;
&lt;h1&gt;
  
  
  Task Parallel Library (TPL)
&lt;/h1&gt;

&lt;p&gt;Una de las deficiencias del uso de subprocesos, hilos, múltiples hilos es que consumen muchos recursos. Cuando se inicia un subproceso este compite con más subprocesos por tiempo de ejecución en la CPU, y gestionar todo esto para el Desarrollador de Software es sumamente complejo, afortunadamente .NET cuenta con el Task Parallel Library (TPL) un conjunto de clases contenidas en el espacio de nombres System.Threading y System.Threading.Task que tienen como finalidad hacer que los Desarrolladores de Software sean más productivos reutilizando clases que optimizan el trabajo de agregar paralelismo y simultaneidad en aplicaciones, TPL se encarga por nosotros de escalar el grado de simultaneidad dinámicamente para usar eficazmente todos los procesadores disponibles en el host, TPL controla la partición del trabajo, la programación de subprocesos en el ThreadPool, permite cancelaciones, administración de estado y otros detalles que preocupan a bajo nivel.&lt;/p&gt;
&lt;h1&gt;
  
  
  La clase Task (Tarea)
&lt;/h1&gt;

&lt;p&gt;La clase Task fue introducida por Microsoft a partir de .NET Framework 4. Una Task (Tarea) es un objeto que representa un trabajo que debe hacerse, Task puede decir si el trabajo se ha completado, si la operación devuelve un resultado o no, en caso de que si devuelva un resultado Task te permite hacer lo que sea con ese resultado, el Task Scheduler (Planificador de Tareas) es el responsable de iniciar Tasks y administrarlas, por defecto el Task Scheduler utiliza Threads (Hilos) del Thread Pool (Grupo de Hilos) para ejecutar Tasks.&lt;br&gt;
Veamos un ejemplo con Código C#.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;NUMBER_OF_ITERATIONS&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;32&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;RunTasksCorrected&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;[]&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;double&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;[&lt;/span&gt;&lt;span class="n"&gt;NUMBER_OF_ITERATIONS&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

   &lt;span class="c1"&gt;// Creamos una tarea por iteración.&lt;/span&gt;
   &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;NUMBER_OF_ITERATIONS&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;++)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;DoIntensiveCalculations&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="c1"&gt;// Esperar a que terminen todas las Tareas&lt;/span&gt;
   &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WaitAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="c1"&gt;// Recopilar los resultados&lt;/span&gt;
   &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="c1"&gt;// Imprimir el resultado&lt;/span&gt;
   &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"El resultado es {0}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;RunTasksCorrected&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Observemos que podemos lanzar múltiples Tareas a ejecución y esto hará que nuestra aplicación sea más receptiva, ya que sí el Thread que maneja la interfaz de usuario descarga el trabajo a realizar a otro Thread del Thread Pool puede seguir procesando eventos de usuario y garantizar que la aplicación aún se puede usar.&lt;br&gt;
Task se encarga por nosotros de gestionar las condiciones de carrera que ocurren cuando dos o más procesos acceden a un recurso compartido sin control, si esto no se administra o no se toma en cuenta el resultado es erróneo y depende del orden de llegada de la Tarea. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Consejo de expertos y especialistas en C#:&lt;/strong&gt; No es necesario llamar a WaitAll ya que task.Result bloqueara al autor de la llamada si la Task aún no finalizo de realizar el cálculo. Entonces, si alguna de las tasks no se realiza cuando ingresa al bucle foreach, la petición que llama se bloqueará y esperará a que termine la tarea.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;
  
  
  Task Scheduler (Manejador de Tareas)
&lt;/h1&gt;

&lt;p&gt;El Task Scheduler realiza el trabajo de poner en cola las Tareas en subprocesos, la clase TaskScheduler se encarga de esta responsabilidad. Cada vez que se inicia una Task si no se especifica un Scheduler se inicia uno por defecto. Los desarrolladores de software debemos tener en cuenta un aspecto muy importante cuando se crea software que utiliza interfaz gráfica como en proyectos Windows Forms, WPF o Xamarin.Forms, recodemos que la interfaz de usuario solo se puede actualizar mediante el Thread principal que administra la interfaz de usuario, por lo que si una Task necesita actualizar la interfaz de usuario debe hacerlo mediante el Thread que gestiona la interfaz de usuario. Para lograr este objetivo se debe llamar a una de las sobrecargas de StartNew o ContinueWith que toman como parámetro un TaskScheduler y pasarle TaskScheduler&lt;br&gt;
.FromCurrentSynchronizationContext() como valor. Por ejemplo supongamos que tenemos una aplicación Xamarin.Forms que contiene un método llamado UpdateProgressBar() que actualiza un ProgressBar en el Thread de la interfaz de usuario, usaríamos lo siguiente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Factory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StartNew&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;UpdateProgressBar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                      &lt;span class="n"&gt;CancellationToken&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                      &lt;span class="n"&gt;TaskCreationOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
             &lt;span class="n"&gt;TaskScheduler&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FromCurrentSynchronizationContext&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De esta manera el Thread de la interfaz de usuario actualizará la interfaz de usuario tan pronto como pueda procesarlo.&lt;/p&gt;

&lt;h1&gt;
  
  
  Parallel Class
&lt;/h1&gt;

&lt;p&gt;El espacio de nombres System.Threading.Tasks también contiene otra clase que podemos utilizar para el procesamiento paralelo. La clase Paralela tiene un par de métodos estáticos: For, ForEach e Invoke: que podemos usar para paralelizar el trabajo.&lt;br&gt;
El paralelismo implica tomar una determinada tarea y dividirla en un conjunto de Tasks relacionadas que pueden ser ejecutadas simultáneamente, esto tampoco significa tengamos que revisar todo nuestro código y reemplazar todos los bucles que tengamos por bucles paralelos. Es recomendable utilizar la clase paralela solo cuando nuestro código no tiene que ejecutarse secuencialmente.&lt;br&gt;
A continuación utilizaremos el método For de la clase Parallel el cuál está definido por la siguiente firma.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;ParallelLoopResult&lt;/span&gt; &lt;span class="n"&gt;For&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TLocal&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;fromInclusive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;toExclusive&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TLocal&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;localInit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ParallelLoopState&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TLocal&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TLocal&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;TLocal&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;localFinally&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Haremos una implementación siguiendo el ejemplo anterior pero esta vez con la clase Parallel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;RunParallelFor&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0d&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="c1"&gt;// Aquí llamamos al mismo metodo varias veces&lt;/span&gt;
   &lt;span class="c1"&gt;//for (int i = 0; i &amp;lt; NUMBER_OF_ITERATIONS; i++)&lt;/span&gt;
   &lt;span class="n"&gt;Parallel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;For&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;NUMBER_OF_ITERATIONS&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="c1"&gt;// Func&amp;lt;TLocal&amp;gt; localInt,&lt;/span&gt;
   &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

   &lt;span class="c1"&gt;// Func&amp;lt;int, ParallelLoopState, TLocal, TLocal&amp;gt; body,&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;interimResult&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;interimResult&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="nf"&gt;DoIntensiveCalculations&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;

   &lt;span class="c1"&gt;// Paso final despues de los calculos&lt;/span&gt;
   &lt;span class="c1"&gt;// Agregaremos el resultado al resultado final&lt;/span&gt;
   &lt;span class="c1"&gt;// Action&amp;lt;TLocal&amp;gt; localFinally&lt;/span&gt;
   &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;lastInterimResult&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;lastInterimResult&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"El resultado es: {0}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="nf"&gt;RunParallelFor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;El tema del rendimiento es algo muy importante a tomar en cuenta en nuestras aplicaciones, y especificamente con el procesamiento en paralelo y multithreading este aumenta cuando tenemos mucho trabajo que realizar que se pueda ejecutar en paralelo. Para cargas de trabajo pequeñas o trabajos que tienen que sincronizar el acceso a los recursos el uso de la clase Parallel puede afectar el rendimiento, la manera de saber si funcionará en nuestros escenarios es medir los resultados con la siguiente y muy sencilla implementación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;Parallel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;For&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Parallel.For: {0} , Task Id: {1}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;

   &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;numbers&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Enumerable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="n"&gt;Parallel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ForEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;numbers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Parallel.Foreach: {0}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusiones&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Escribir código que maneja múltiples Threads es altamente díficil debido a que hay muchas cosas a tomar en cuenta como el stack, el heap, datos, memoria, condiciones de carrera y otros aspectos que ocurren a bajo nivel cuando de multithreading se trata.&lt;/li&gt;
&lt;li&gt;Aunque existe la clase Thread y ThreadPool es recomendable no utilizarlas directamente, en su lugar Microsoft y expertos en C# recomiendan TPL.&lt;/li&gt;
&lt;li&gt;Antiguamente tener un procesador significaba que sólo un subproceso se podía ejecutar a la vez, actualmente con la llegada de los nuevos procesadores multinúcleo y de muchos núcleos, las aplicaciones que se escriben de forma multihilo o asíncrona se benefician intrínsecamente de esas mejoras, mientras que las aplicaciones escritas secuencialmente ignoran los recursos  disponibles y hacen que el usuario espere innecesariamente lo que nos lleva a una mala experiencia de usuario.&lt;/li&gt;
&lt;li&gt;Un Thread puede verse como una CPU virtualizada.&lt;/li&gt;
&lt;li&gt;El uso de varios threads puede mejorar la capacidad de respuesta y permite utilizar múltiples procesadores.&lt;/li&gt;
&lt;li&gt;Un objeto Task encapsula un trabajo que debe ejecutarse. Las tareas son la forma recomendada de crear código multithread.&lt;/li&gt;
&lt;li&gt;Con TPL podemos debuguear código asíncrono como si fuera síncrono en Visual Studio.&lt;/li&gt;
&lt;li&gt;Task Parallel Library (TPL), básicamente proporciona un mayor nivel de abstracción.&lt;/li&gt;
&lt;li&gt;El objetivo principal TPL es dar a los desarrolladores la oportunidad de agregar paralelismo y/o simultaneidad a sus aplicaciones.&lt;/li&gt;
&lt;li&gt;Una Task es una manera más fácil de ejecutar algo de forma asincrónica y en paralelo en comparación con un subproceso.&lt;/li&gt;
&lt;li&gt;TPL es una biblioteca muy extensa por lo que considero que sería oportuno extender este Post en una segunda parte y hablar acerca de async y await palabras clave en el uso de TPL, el procesamiento multithreading y programación asincrona.&lt;/li&gt;
&lt;li&gt;TPL también nos proporciona la clase Parallel para paralelizar cargas de trabajo.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Referencias:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/task-parallel-library-tpl"&gt;https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/task-parallel-library-tpl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://dl.acm.org/doi/abs/10.1145/1639949.1640106"&gt;https://dl.acm.org/doi/abs/10.1145/1639949.1640106&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://books.google.es/books?hl=es&amp;amp;lr=&amp;amp;id=nBsGVjwzBJEC&amp;amp;oi=fnd&amp;amp;pg=PT7&amp;amp;dq=task+parallel+library+c%23&amp;amp;ots=V5yE1nyR6e&amp;amp;sig=PPo0YGPBXbSFl3Xuw_ZUW5Y1PjY#v=onepage&amp;amp;q=task%20parallel%20library%20c%23&amp;amp;f=false"&gt;https://books.google.es/books?hl=es&amp;amp;lr=&amp;amp;id=nBsGVjwzBJEC&amp;amp;oi=fnd&amp;amp;pg=PT7&amp;amp;dq=task+parallel+library+c%23&amp;amp;ots=V5yE1nyR6e&amp;amp;sig=PPo0YGPBXbSFl3Xuw_ZUW5Y1PjY#v=onepage&amp;amp;q=task%20parallel%20library%20c%23&amp;amp;f=false&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Píldoras de C#: Delegates, Métodos Anónimos, Expresiones Lambda y Eventos</title>
      <dc:creator>Eduardo Barrios</dc:creator>
      <pubDate>Sun, 01 Nov 2020 21:21:03 +0000</pubDate>
      <link>https://forem.com/ebarrioscode/pildoras-de-c-delegates-metodos-anonimos-expresiones-lambda-y-eventos-3ah8</link>
      <guid>https://forem.com/ebarrioscode/pildoras-de-c-delegates-metodos-anonimos-expresiones-lambda-y-eventos-3ah8</guid>
      <description>&lt;p&gt;En alguna ocasión te has preguntado como almacenar un método en un tipo de dato de C#, o te has preguntado como pasar un método como parámetro a otro método y como carajos funcionan los eventos. Estás características lenguajes de programación como JavaScript lo hacen a menudo, por su parte C# puede lograr todo esto mediante Delegates. En este Post abordaremos los siguientes puntos sobre delegates en C#.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;¿Qué es un Delegate, como creo un Delegate?&lt;/li&gt;
&lt;li&gt;Delegates integrados de .NET&lt;/li&gt;
&lt;li&gt;Métodos Anónimos&lt;/li&gt;
&lt;li&gt;Expresiones Lambda&lt;/li&gt;
&lt;li&gt;Eventos&lt;/li&gt;
&lt;li&gt;Utilizando Delegates (Xamarin Forms, ASP.NET Core WebApi)&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Qué es un Delegate
&lt;/h1&gt;

&lt;p&gt;Un delegate en C# es un tipo de dato como lo es una estructura, o una clase, estos tipos definen propiedades, métodos y algunas veces eventos, por su parte los delegates se encargan de referenciar métodos que coincidan con una firma compatible determinada por los parámetros de entrada y tipo de retorno. Podemos comparar los delegates con los punteros de C++, un delegate de C# apunta a la dirección en memoria de 1 o más métodos esto gracias a la Multidifusión que permite anidar métodos a una instancia de un tipo delegate, los delegates de C# nos permiten crear instancias de un tipo delegate y dejar que apunte a otro método y así mismo invocar el método a través de la instancia del tipo delegate, esto es muy útil para poder pasar métodos como parámetros hacía otros métodos o para poder crear manejadores de Eventos que no son más que métodos que se invocan mediante delegates.&lt;br&gt;
Imaginemos los siguientes casos, una aplicación de escritorio desarrollada con Windows Form poseé una interfaz gráfica con elementos Button, Combobox, TextBox, etc, el usuario puede realizar acciones presionando click sobre un Button o cualquiera de los otros elementos visuales, la acción de realizar un click desencadena un Evento, aquí entran los delegates ya que podemos manejar ese evento y hacer múltiples cosas mediante un manejador de eventos que se suscriba al Evento lanzado, lo importante en este aspecto es que fue un delegate el que invoco el Evento.&lt;br&gt;
Veamos el caso de una Aplicación Móvil desarrollada con Xamarin Forms, supongamos que tenemos un Content Page que internamente contiene un ListView con objetos genéricos, la acción de realizar un Tap sobre cualquier item o Swipe desencadenará un Evento y es aquí donde otra vez vemos delegates en acción.&lt;br&gt;
C# es un lenguaje de programación fuertemente tipado y muchos de los tipos contenidos dentro de los Assemblies de DotNet funcionan entorno a delegates.&lt;br&gt;
Los delegates de C# podemos crearlos personalizados es decir crear nuestros propios tipos definiendo una firma especifica o podemos reutilizar los propios delegates de DotNet que veremos más adelante.&lt;/p&gt;

&lt;p&gt;Veamos como crear un tipo delegate, la siguiente sintaxis define su estructura&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;identificador&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;acceso&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;delegate&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Tipo&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;retorno&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Nombre&lt;/span&gt; &lt;span class="n"&gt;del&lt;/span&gt; &lt;span class="n"&gt;Delegate&lt;/span&gt;&lt;span class="p"&gt;]([&lt;/span&gt;&lt;span class="n"&gt;Par&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;metros&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;entrada&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Con base en la sintaxis anterior crearemos un delegate que apunte a métodos con coincidan con una firma determinada.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;delegate&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;CalculateDelegate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mejores prácticas:&lt;/strong&gt; Algunos programadores agregan la palabra Delegate al final del nombre del tipo Delegate. Esto es muy común pero no es universal tampoco obligatorio.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ahora necesitamos métodos para almacenar en nuestro tipo Delegate y hacer uso del tipo Delegate para referenciar esos métodos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TestDelegate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;CalculateDelegate&lt;/span&gt; &lt;span class="n"&gt;instanceDelegate&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;instanceDelegate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Salida 9&lt;/span&gt;

   &lt;span class="n"&gt;instanceDelegate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Multiply&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;instanceDelegate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Salida 20&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hemos creado un tipo Delegate muy básico y tenemos una instancia que podríamos utilizar para presentárselo a un método como argumento. Como podemos observar el código anterior solo instanciamos una vez el tipo Delegate y la segunda vez asignamos un segundo método sin nada más, esto gracias a que desde C# 2.0 se agregó la creación automática de un nuevo delegate cuando se asigna un grupo de métodos a un tipo delegate.&lt;/p&gt;

&lt;p&gt;Otra característica importante de los Delegates de C# es la multidifusión que permite combinar y anidar métodos a la lista de invocación de una instancia de delegado existente, utilizamos el operador + o += para lograrlo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;MethodOne&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Método 1"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;MethodTwo&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Método 2"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 

&lt;span class="c1"&gt;// Definir el Tipo Delegate&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;delegate&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;FunctionDelegate&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TestMulticast&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;FunctionDelegate&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;MethodOne&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;MethodTwo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="nf"&gt;d&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Salida:&lt;/span&gt;
&lt;span class="c1"&gt;// Método 1&lt;/span&gt;
&lt;span class="c1"&gt;// Método 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; La multidifusión de los Delegates es la característica que permite suscribirse a Eventos y manejadores de Eventos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Delegates integrados de .NET
&lt;/h1&gt;

&lt;p&gt;.NET define dos tipos de delegates genéricos(Action y Func) ambos los podemos utilizar para evitar definir nuestros propios delegates.&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;Delegate Action&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;El Delegate genérico Action representa un método que devuelve void. Diferentes versiones de Action toman entre 0 y 16 parámetros de entrada, a menos que necesitemos un delegate que tome más de 16 parámetros de entrada y devolver void se recomienda utilizar Action.&lt;br&gt;
Veamos el ejemplo anterior de los métodos Add y Multiply que toman dos tipos int como parámetros de entrada y en este caso devuelven void. Cambiaremos la firma de ambos métodos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TestDelegate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Salida 9&lt;/span&gt;

   &lt;span class="n"&gt;action&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Multiply&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="nf"&gt;action&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Salida 20&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Action en su declaración toma dos tipos int, ambos hacen referencia a los dos parámetros de entrada tipo int que son requeridos y deben coincidir con la firma del método y el delegate.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;Delegate Func&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;El Delegate Func es otro de los tipos integrados de .NET que representa un método que devuelve un valor, como el caso de Action, Func tiene múltiples versiones que toman entre 0 y 16 parámetros de entrada y a menos que no sea necesario presentar más de 16 parámetros de entrada y devolver un valor se recomienda utilizar el tipo delegate Func. Veamos el ejemplo anterior de los métodos Add y Multiply que toman 2 parámetros de entrada tipo int y devuelven un int como resultado, para esto regresaremos a la firma de ambos métodos como fueron definidos en un principio.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;Multiply&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TestDelegate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Add&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Salida 9&lt;/span&gt;

   &lt;span class="n"&gt;func&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Multiply&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// Salida 20&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Func en su declaración toma 3 tipos int, los primeros dos tipos int representan la cantidad de parámetros de entrada, en este caso son 2 valores de tipo int, el tercer int en la declaración del delegate Func hace referencia al tipo a devolver, el resultado de la operación será un int y la firma de ambos métodos especifican que deben devolver un tipo int.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  &lt;em&gt;Delegate Predicate&lt;/em&gt;
&lt;/h4&gt;

&lt;p&gt;Predicate es otro Delegate integrado de .NET como lo son Action y Func. Predicate está definido por la siguiente firma.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;delegate&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="n"&gt;Predicate&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Predicate representa un método que contiene un conjunto de criterios a verificar y valida si el parámetro pasado cumple con esos criterios. Es obligatorio para Predicate pasar un parámetro de entrada y siempre devuelve un booleano true o false.&lt;br&gt;
Veamos un ejemplo para entender como funciona Predicate.&lt;br&gt;
Supongamos que necesitamos validar cuentas de correo electrónico, tenemos una lista de cadenas que contiene múltiples cuentas de correo electrónico, pero entre la lista existen cuentas de correo electrónico no validas, con base en esa primer lista necesitamos crear una segunda lista que contenga solo las cuentas de correo electrónico válidas. Crearemos un Delegate Predicate para lograr este objetivo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Método que pasaremos al Delegate Predicate&lt;/span&gt;
&lt;span class="c1"&gt;// Este método devolverá true o false dependiendo si el email es válido&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="nf"&gt;EmailIsValid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;@"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Regex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TestDelegate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="c1"&gt;// Lista de emails&lt;/span&gt;
   &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;emails&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;List&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;()&lt;/span&gt;
           &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="s"&gt;"admin@gmail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"admin@gmail"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"2gmail.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"test@hotmail.com"&lt;/span&gt;
            &lt;span class="p"&gt;};&lt;/span&gt;

   &lt;span class="c1"&gt;// Creamos el Predicate&lt;/span&gt;
   &lt;span class="n"&gt;Predicate&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;predicate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Predicate&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;EmailIsValid&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="c1"&gt;// Utilizamos el Predicate para crear una nueva lista con emails válidos&lt;/span&gt;
   &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;validEmails&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FindAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;predicate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="c1"&gt;// Recorremos la nueva lista&lt;/span&gt;
   &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;validEmails&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// El resultado es:&lt;/span&gt;
&lt;span class="c1"&gt;// admin@gmail.com&lt;/span&gt;
&lt;span class="c1"&gt;// test@hotmail.com&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Métodos Anónimos
&lt;/h1&gt;

&lt;p&gt;Los métodos anónimos no son más que métodos sin nombre. En lugar de crear métodos como normalmente lo hacemos creamos un delegado que haga referencia al código que debería contener el método tradicional internamente, con esto podremos utilizar ese delegado como si fuera una variable de delegado que contiene una referencia al método. A continuación la sintaxis correcta para crear un método anónimo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;delegate&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="n"&gt;par&lt;/span&gt;&lt;span class="err"&gt;á&lt;/span&gt;&lt;span class="n"&gt;metros&lt;/span&gt; &lt;span class="n"&gt;de&lt;/span&gt; &lt;span class="n"&gt;entrada&lt;/span&gt;&lt;span class="p"&gt;]){&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="err"&gt;ó&lt;/span&gt;&lt;span class="n"&gt;digo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modifiquemos el caso anterior pero ahora en lugar de pasar como argumento el método tradicional que cumple con la firma de un Predicate, pasaremos la definición del método como argumento y como un método anónimo.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TestPredicate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;Predicate&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;predicate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;Predicate&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;(&lt;/span&gt;
                     &lt;span class="k"&gt;delegate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                     &lt;span class="p"&gt;{&lt;/span&gt;
                       &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;@"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
                       &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Regex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IsMatch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;pattern&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                      &lt;span class="p"&gt;});&lt;/span&gt;

   &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;validEmails&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;emails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FindAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;predicate&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

   &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;validEmails&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Expresiones Lambda
&lt;/h1&gt;

&lt;p&gt;Suelen suceder casos en los que la firma completa de un método puede ser más código que el propio cuerpo del método, también hay situaciones en las que necesitamos crear un método completo solo para usarlo en un delegado. Para esos casos Microsoft agregó algunas características importantes y útiles en C#. En C# 2.0 se agregaron los métodos anónimos, en C# 3.0 mejoraron aún más cuando se agregaron las expresiones lambda. Las expresiones lambda nos permiten utilizar una sintaxis concisa y más corta para que de otra forma podamos escribir métodos anónimos. &lt;br&gt;
A continuación la sintaxis correcta para escribir una expresión lambda.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;expression&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Los paréntesis vacíos representan la lista de parámetros vacía tomada por el método anónimo, =&amp;gt; indica que se trata de una expresión lambda, en este caso la expresión lambda es de una sola instrucción, si el método necesita más de una instrucción se deben agregar {} de la siguiente manera.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; 
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Instrucción 1;&lt;/span&gt;
  &lt;span class="c1"&gt;// Instrucción 2;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota Importante:&lt;/strong&gt; Pasar parámetros de entrada a un método anónimo con sintaxis de expresión lambda es sumamente sencillo, debemos agregar los parámetros dentro de los paréntesis de la expresión, cuando es un solo parámetro podemos omitir los paréntesis y escribir únicamente el nombre del único parámetro. Otro punto importante es el tipo de los parámetros podemos agregarlos o dejar que la característica de inferencia de tipos de C# haga el trabajo.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Pasando un solo parámetro&lt;/span&gt;
&lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;action1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nombre&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Hola &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;nombre&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Pasando un solo parámetro sin los paréntesis&lt;/span&gt;
&lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;action2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nombre&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;$"Hola &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;nombre&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Pasando dos parámetros sin especificar el tipo&lt;/span&gt;
&lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;action3&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Pasando dos parámetros especificando el tipo&lt;/span&gt;
&lt;span class="n"&gt;Action&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;action4&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="p"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Mejores Prácticas:&lt;/strong&gt; Incluir los paréntesis aunque solo necesitemos un parámetro de entrada para una expresión lambda es una buena práctica ya que hace más legible el código. Naturalmente las expresiones lambda ya son bastante confusas por lo que muchos desarrolladores las incluyen aunque no sean necesarias.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Eventos
&lt;/h1&gt;

&lt;p&gt;Los eventos permiten que exista una comunicación entre objetos y un programa para indicar cuando algo interesante ha sucedido o se ha bloqueado, por ejemplo un objeto de correo electrónico podría generar un evento para indicar al programa que ha recibido un mensaje nuevo. &lt;br&gt;
Una solución reutilizable para problemas recurrentes con base en eventos en el desarrollo de aplicaciones es el de Editor-Suscriptor, consiste en suscribirse a un evento y luego notificar cuando el editor del evento plantea un nuevo evento, naturalmente esto se usa para establecer un acoplamiento flojo en componentes de una aplicación.&lt;br&gt;
A continuación un ejemplo sencillo del patrón Editor-Suscriptor y Eventos.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Editor&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;event&lt;/span&gt; &lt;span class="n"&gt;Action&lt;/span&gt; &lt;span class="n"&gt;OnChange&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;delegate&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;

   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;Raise&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="nf"&gt;OnChange&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;TestEvents&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="n"&gt;Editor&lt;/span&gt; &lt;span class="n"&gt;editor&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Editor&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnChange&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Evento generado en el método 1"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OnChange&lt;/span&gt; &lt;span class="p"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;WriteLine&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Evento generado en el método 2"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="n"&gt;editor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Raise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Utilizando Delegates
&lt;/h1&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Xamarin Forms&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Pensemos en el siguiente escenario. Tenemos una aplicación móvil desarrollada con Xamarin Forms que contiene un control Entry que recibe el nombre del usuario y existe un control Button que al presionarlo muestra un Dialogo que saluda al usuario, pensando como desarrollador Xamarin lo resolvemos haciendo un Binding a la propiedad Text del Entry y otro Binding a la propiedad Command del control Button, una vez que tenemos capturado el valor del Entry creamos el Command que se ejecutara cuando el usuario presione el Button y nuestro Command quedaria de la siguiente manera.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ICommand&lt;/span&gt; &lt;span class="n"&gt;ExecuteCommand&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;get&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ExecuteMethod&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;ExecuteMethod&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MainPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DisplayAlert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Delegates App"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;$"Hola: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Ok"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Está es la manera más habitual para resolver el problema planteado, pero observemos la nueva instancia de Command, Command según la documentación oficial de Microsoft todas las sobrecargas de constructores reciben delegates como parámetros los ya conocidos anteriormente tipos integrados por .NET Action y Func. Lo que estamos haciendo es utilizar delegates y tal vez ves no lo sabias.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4ahfff8lbx0hhxphmflg.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4ahfff8lbx0hhxphmflg.PNG" alt="Alt Text" width="800" height="247"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Podemos variar la implementación tradicional pero antes analizar si en lugar de escribir un método completo con una firma más extensa que el propio cuerpo del método o si el delegado que necesita nuestro Command solo se utilizará una vez podemos pasar como parámetro al Command un método anónimo como tal o con sintaxis de expresión lambda como lo haremos a continuación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ICommand&lt;/span&gt; &lt;span class="n"&gt;ExecuteCommand&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;get&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// Pasando el delegate como método anónimo a la nueva instancia de Command&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;delegate&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MainPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DisplayAlert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Delegates App"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;$"Hola: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Ok"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;get&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;value&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;ICommand&lt;/span&gt; &lt;span class="n"&gt;ExecuteCommand&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;get&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// Pasando el delegate como método anónimo con sintaxis lambda a la nueva instancia de Command&lt;/span&gt;
     &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;Command&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Current&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MainPage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DisplayAlert&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Delegates App"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;$"Hola: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Ok"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;ASP.NET Core WebApi&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Pensemos en el siguiente escenario. Tenemos un WebApi desarrollado con DotNet Core con una implementación genérica del patrón Repository y UnitOfWork. Esta implementación cuenta con un método Get que devuelve una lista genérica de objetos después de heredar implementaciones en una clase abstracta y no recibe ningún parámetro de entrada. El método Get de momento solo devuelve una lista mediante un contexto de Entity Framework, el nuevo requerimiento es que debemos poder agregar condiciones Where pasadas como argumento y como expresión lambda al método Get para poder filtrar los objetos por condiciones genéricas, otro requerimiento es poder ordenar esa lista pasando una expresión lambda como argumento al método Get y por último agregar Includes para obtener información adicional con objetos relacionados mediante sus propiedades de navegación.&lt;br&gt;
Necesitamos pasar expresiones lambda como argumentos al método Get, bueno pensemos en delegates, realmente podría escribir un tipo delegate personalizado, pero considero que no es necesario y podría aprovechar la existencia de los tipos integrados de .Net. Con base en los requerimientos necesitamos devolver un valor y necesitamos pasar parámetros pensemos en resolver la problemática con el Delegate Func, la implementación con los nuevos requermientos quedaría de la siguiente manera.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IGenericRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;
&lt;span class="err"&gt;{&lt;/span&gt;
   &lt;span class="nc"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Expression&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;whereCondition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                      &lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IQueryable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;IOrderedQueryable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;orderBy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
                      &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;includeProperties&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;abstract&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GenericRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IGenericRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="k"&gt;where&lt;/span&gt; &lt;span class="n"&gt;T&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;
&lt;span class="err"&gt;{&lt;/span&gt;
   &lt;span class="nc"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IUnitOfWork&lt;/span&gt; &lt;span class="n"&gt;_unitOfWork&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;GenericRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IUnitOfWork&lt;/span&gt; &lt;span class="n"&gt;unitOfWork&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;_unitOfWork&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;unitOfWork&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;IEnumerable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Expression&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;whereCondition&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="n"&gt;Func&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IQueryable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;IOrderedQueryable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;orderBy&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                         &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;includeProperties&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="n"&gt;IQueryable&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;_unitOfWork&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;whereCondition&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;whereCondition&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;foreach&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;includeProperty&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;includeProperties&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="sc"&gt;','&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="n"&gt;StringSplitOptions&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemoveEmptyEntries&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;includeProperty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;orderBy&lt;/span&gt; &lt;span class="p"&gt;!=&lt;/span&gt; &lt;span class="k"&gt;null&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;orderBy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

      &lt;span class="k"&gt;else&lt;/span&gt;
         &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ToList&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;         
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Hemos agregado el Delegate Func a la firma del Método Get para cumplir los requerimientos, ahora vamos a probar y para eso necesitamos heredar del Repositorio Genérico.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Modelo Product necesario para una implementación de un CustomRepository&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Product&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;ProductID&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="n"&gt;Description&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;double&lt;/span&gt; &lt;span class="n"&gt;Price&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt; &lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;get&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IProductRepository&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;IGenericRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Implementación del CustomRepository&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;ProductRepository&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;GenericRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;,&lt;/span&gt; &lt;span class="n"&gt;IProductRepository&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;ProductRepository&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IUnitOfWork&lt;/span&gt; &lt;span class="n"&gt;_unitOfWork&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;base&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;_unitOfWork&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Con los requerimientos completados podemos recuperar objetos según cualquier condición, ordenar por cualquier propiedad del modelo e incluir relaciones.&lt;br&gt;
Recuperemos los productos que tengan fecha de hoy, ordenados por su precio del más alto hasta el más bajo y sin ninguna relación, el siguiente código realiza esa tarea.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Prueba del método Get con los nuevos requermientos&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TestDelegateWebApi&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IProductRepository&lt;/span&gt; &lt;span class="n"&gt;_customRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;TestDelegateWebApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IProductRepository&lt;/span&gt; &lt;span class="n"&gt;customRepository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_customRepository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;customRepository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;

   &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;GetProducts&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
   &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;products&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;_customRepository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Date&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="n"&gt;DateTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;OrderByDescending&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Price&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Empty&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
   &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Conclusiones&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Es importante saber como crear nuestros propios tipos delegados pero también es importante evitarlo y según nuestras necesidades debemos reutilizar los tipos integrados de .NET.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Los delegados forman la base del sistema de eventos en C#.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Escribir métodos de manera anónima o como expresión lambda es opcional y depende del programador.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Los eventos en C# no son propios de un tipo de proyecto de .NET sino del lenguaje C# como tal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Microsoft recomienda que todos los eventos proporcionen dos parámetros: el objeto que genera el evento y otro objeto que proporciona argumentos que son relevantes para el evento. El segundo objeto debe ser de una clase derivada de la Clase EventArgs.  &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Referencias:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.command?view=xamarin-forms" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/dotnet/api/xamarin.forms.command?view=xamarin-forms&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/es-es/dotnet/csharp/programming-guide/delegates/" rel="noopener noreferrer"&gt;https://docs.microsoft.com/es-es/dotnet/csharp/programming-guide/delegates/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/es-es/previous-versions/visualstudio/visual-studio-2008/ff518995(v=orm.10)" rel="noopener noreferrer"&gt;https://docs.microsoft.com/es-es/previous-versions/visualstudio/visual-studio-2008/ff518995(v=orm.10)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Code Snippets Entity Framework Core para Xamarin Forms</title>
      <dc:creator>Eduardo Barrios</dc:creator>
      <pubDate>Mon, 29 Jun 2020 14:18:02 +0000</pubDate>
      <link>https://forem.com/ebarrioscode/code-snippets-entity-framework-core-para-xamarin-forms-4277</link>
      <guid>https://forem.com/ebarrioscode/code-snippets-entity-framework-core-para-xamarin-forms-4277</guid>
      <description>&lt;p&gt;Este Post forma parte del &lt;strong&gt;Xamarin Month 2020&lt;/strong&gt; una iniciativa de Luis Matos, con un enfoque en Code Snippets útiles en el desarrollo de aplicaciones móviles con Xamarin Forms y Visual Studio ya sea para Windows o Mac. Puedes revisar el resto de contribuciones realizadas por increíbles autores, profesionales y miembros de la comunidad de Xamarin en el siguiente enlace =&amp;gt; &lt;a href="https://luismts.com/code-snippetss-xamarin-month/" rel="noopener noreferrer"&gt;XamarinMonth&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Entity Framework Core&lt;/strong&gt; es el ORM favorito de muchos desarrolladores de software .NET, personalmente me parece genial y lo utilizo muy a menudo, es por eso que quiero compartir con contigo algunos Code Snippets que te podrían ser útiles. Cuando de utilizar Entity Framework Core se trata siempre estamos obligados a escribir un Contexto de Datos que se encargará de gestionar la conexión a la Base de datos, además de utilizar el Dependency Service de Xamarin Forms para implementar funcionalidades especificas de cada plataforma.&lt;/p&gt;

&lt;p&gt;Los Code Snippets que crearemos en este Post serán:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Contexto de Datos &lt;em&gt;AppDbContext.cs&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Interface de Configuración para obtener el Directorio de BD de cada plataforma &lt;em&gt;IConfigDataBase.cs&lt;/em&gt; &lt;/li&gt;
&lt;li&gt;Implementaciones especificas de Android y iOS &lt;em&gt;ConfigDataBase.cs&lt;/em&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Creando el primer Code Snippet
&lt;/h1&gt;

&lt;p&gt;Para crear Code Snippets para Visual Studio en Windows lo que necesitamos es crear un archivo .xml, llenar los elementos correspondientes y agregar el código.&lt;br&gt;
La Documentación oficial de Microsoft nos proporciona un archivo .xml que contiene la plantilla básica para crear nuestro primer fragmento de código.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;CodeSnippets&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;CodeSnippet&lt;/span&gt; &lt;span class="na"&gt;Format=&lt;/span&gt;&lt;span class="s"&gt;"1.0.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Header&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Title&amp;gt;&amp;lt;/Title&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/Header&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Snippet&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Code&lt;/span&gt; &lt;span class="na"&gt;Language=&lt;/span&gt;&lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="cp"&gt;&amp;lt;![CDATA[]]&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/Code&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/Snippet&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/CodeSnippet&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/CodeSnippets&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Code Snippet AppDbContext.cs
&lt;/h2&gt;

&lt;p&gt;Crearemos un archivo llamado &lt;em&gt;DbContext.snippet&lt;/em&gt; en la siguiente ruta &lt;strong&gt;%USERPROFILE%\Documents\Visual Studio 2019\Code Snippets\Visual C#\My Code Snippets&lt;/strong&gt;, con base en la plantilla anterior llenaremos los elementos y agregaremos el código.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;CodeSnippets&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;CodeSnippet&lt;/span&gt; &lt;span class="na"&gt;Format=&lt;/span&gt;&lt;span class="s"&gt;"1.0.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Header&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Title&amp;gt;&lt;/span&gt;DbContext&lt;span class="nt"&gt;&amp;lt;/Title&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Author&amp;gt;&lt;/span&gt;Eduardo Barrios&lt;span class="nt"&gt;&amp;lt;/Author&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Description&amp;gt;&lt;/span&gt;Crea un Contexto de Datos Entity Framework Core para Xamarin Forms.&lt;span class="nt"&gt;&amp;lt;/Description&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Shortcut&amp;gt;&lt;/span&gt;dbcontext&lt;span class="nt"&gt;&amp;lt;/Shortcut&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/Header&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Snippet&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Code&lt;/span&gt; &lt;span class="na"&gt;Language=&lt;/span&gt;&lt;span class="s"&gt;"CSharp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="cp"&gt;&amp;lt;![CDATA[
                public class AppDbContext : DbContext
                {
                    string DbPath = string.Empty;

                    public AppDbContext(string dbPath)
                    {
                        this.DbPath = dbPath;
                    }     

                    // TODO: Declarar los objetos del modelo

                    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
                    {
                        optionsBuilder.UseSqlite("Filename="+DbPath);
                    }
                }
                ]]&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/Code&amp;gt;&lt;/span&gt;            
          &lt;span class="nt"&gt;&amp;lt;Imports&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Import&amp;gt;&lt;/span&gt;
              &lt;span class="nt"&gt;&amp;lt;Namespace&amp;gt;&lt;/span&gt;Microsoft.EntityFrameworkCore&lt;span class="nt"&gt;&amp;lt;/Namespace&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/Import&amp;gt;&lt;/span&gt;
          &lt;span class="nt"&gt;&amp;lt;/Imports&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/Snippet&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/CodeSnippet&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/CodeSnippets&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Probando Code Snippet AppDbContext
&lt;/h2&gt;

&lt;p&gt;Para probar este code snippet debemos crear una nueva clase llamada AppDbContext para que coincida con el nombre de la clase que creará el code snippet, puedes nombrar de otra manera la clase del contexto y cambiarla en el código del fragmento como te guste.&lt;br&gt;
Borramos los using, la clase completa y solo dejaremos el namespace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqjlm098u3z5if5ar8jki.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqjlm098u3z5if5ar8jki.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Escribimos el shorcut dbcontext, dbcontext hace referencia al tag shorcut que definimos en el archivo .xml, podemos notar que el intellisense de Visual Studio  nos muestra información del Code Snippet que fue definida en el mismo archivo &lt;em&gt;DbContext.snippet&lt;/em&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe03a9vqxlgi36x1levar.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fe03a9vqxlgi36x1levar.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Presionamos la tecla TAB dos veces y veremos como el code snippet funciona correctamente y crea el código predefinido.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4mcz1rpvgpj5hiwt3rvx.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4mcz1rpvgpj5hiwt3rvx.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  Interface de Configuración IConfigDataBase
&lt;/h1&gt;

&lt;p&gt;Repetimos los pasos anteriores para crear el code snippet que nos permitirá crear una interface en el proyecto .NET Standard para su posterior implementación en cada plataforma.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;CodeSnippets&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;CodeSnippet&lt;/span&gt; &lt;span class="na"&gt;Format=&lt;/span&gt;&lt;span class="s"&gt;"1.0.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Header&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Title&amp;gt;&lt;/span&gt;Xamarin-IConfigDataBase&lt;span class="nt"&gt;&amp;lt;/Title&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Author&amp;gt;&lt;/span&gt;Eduardo Barrios&lt;span class="nt"&gt;&amp;lt;/Author&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Description&amp;gt;&lt;/span&gt;Crea una Interface para Configuración de Base de Datos SQLite (Dependency Service).&lt;span class="nt"&gt;&amp;lt;/Description&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Shortcut&amp;gt;&lt;/span&gt;iconfiguration&lt;span class="nt"&gt;&amp;lt;/Shortcut&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/Header&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Snippet&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Code&lt;/span&gt; &lt;span class="na"&gt;Language=&lt;/span&gt;&lt;span class="s"&gt;"CSharp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="cp"&gt;&amp;lt;![CDATA[
                public interface IConfigDataBase
                {
                    string GetFullPath(string databaseFileName);
                }
                ]]&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/Code&amp;gt;&lt;/span&gt;                      
        &lt;span class="nt"&gt;&amp;lt;/Snippet&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/CodeSnippet&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/CodeSnippets&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Crearemos una nueva Interface que por convención se llamará IConfigDataBase.cs, seguidamente escribimos el shorcut &lt;em&gt;iconfiguration&lt;/em&gt; que definimos previamente en el code snippet.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F26e08t5x383wdeh03iih.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F26e08t5x383wdeh03iih.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Presionamos dos veces la tecla TAB y verificamos que nuestro code snippet funciona correctamente.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk8v4mc5lu1lgorvipor4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fk8v4mc5lu1lgorvipor4.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  Code Snippets implementaciones Android y iOS
&lt;/h1&gt;

&lt;p&gt;En los siguientes fragmentos de código agregaremos el código correspondiente para el método GetFullPath(string databaseFileName) y no para la clase completa debido a que debemos implementar la interface creada en el proyecto .NET Standard y el nombre puede ser arbitrario según sea tu decisión y su namespace puede variar.&lt;/p&gt;
&lt;h3&gt;
  
  
  Android
&lt;/h3&gt;

&lt;p&gt;Repetimos el proceso anterior, creamos el archivo con extensión .snippet y lo nombraremos GetFullPathAndroid.snippet, lo guardamos en la ruta correspondiente.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;CodeSnippets&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;CodeSnippet&lt;/span&gt; &lt;span class="na"&gt;Format=&lt;/span&gt;&lt;span class="s"&gt;"1.0.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Header&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Title&amp;gt;&lt;/span&gt;Xamarin-ConfigDataBase&lt;span class="nt"&gt;&amp;lt;/Title&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Author&amp;gt;&lt;/span&gt;Eduardo Barrios&lt;span class="nt"&gt;&amp;lt;/Author&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Description&amp;gt;&lt;/span&gt;Crea el método GetFullPath para obtener la ruta de BD en Android (Dependency Service).&lt;span class="nt"&gt;&amp;lt;/Description&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Shortcut&amp;gt;&lt;/span&gt;getfullpathandroid&lt;span class="nt"&gt;&amp;lt;/Shortcut&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/Header&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Snippet&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Code&lt;/span&gt; &lt;span class="na"&gt;Language=&lt;/span&gt;&lt;span class="s"&gt;"CSharp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="cp"&gt;&amp;lt;![CDATA[                
                public string GetFullPath(string databaseFileName)
                {
                    return Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), databaseFileName);
                }                        
                ]]&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/Code&amp;gt;&lt;/span&gt; 
            &lt;span class="nt"&gt;&amp;lt;Imports&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;Import&amp;gt;&lt;/span&gt;              
                  &lt;span class="nt"&gt;&amp;lt;Namespace&amp;gt;&lt;/span&gt;System.IO&lt;span class="nt"&gt;&amp;lt;/Namespace&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/Import&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/Imports&amp;gt;&lt;/span&gt;                     
        &lt;span class="nt"&gt;&amp;lt;/Snippet&amp;gt;&lt;/span&gt;        
    &lt;span class="nt"&gt;&amp;lt;/CodeSnippet&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/CodeSnippets&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Posterior a guardar el archivo .snippet podremos comprobar que el intellisense de VS nos muestra la opción y la información de nuestro code snippet.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgx0uwjyz1t2qpkz7x94d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgx0uwjyz1t2qpkz7x94d.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Presionamos la tecla TAB dos veces para comprobar el correcto funcionamiento de nuestro code snippet.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw737mgc0pqfkmw6jlx39.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw737mgc0pqfkmw6jlx39.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h3&gt;
  
  
  iOS
&lt;/h3&gt;

&lt;p&gt;Repetimos el proceso anterior, en este caso llamaremos GetFullPathIOS.snippet a nuestro archivo .snippet y lo guardamos en la ruta correspondiente.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;CodeSnippets&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;CodeSnippet&lt;/span&gt; &lt;span class="na"&gt;Format=&lt;/span&gt;&lt;span class="s"&gt;"1.0.0"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Header&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Title&amp;gt;&lt;/span&gt;Xamarin-ConfigDataBase&lt;span class="nt"&gt;&amp;lt;/Title&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Author&amp;gt;&lt;/span&gt;Eduardo Barrios&lt;span class="nt"&gt;&amp;lt;/Author&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Description&amp;gt;&lt;/span&gt;Crea el método GetFullPath para obtener la ruta de BD en iOS (Dependency Service).&lt;span class="nt"&gt;&amp;lt;/Description&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Shortcut&amp;gt;&lt;/span&gt;getfullpathios&lt;span class="nt"&gt;&amp;lt;/Shortcut&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;/Header&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;Snippet&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;Code&lt;/span&gt; &lt;span class="na"&gt;Language=&lt;/span&gt;&lt;span class="s"&gt;"CSharp"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
                &lt;span class="cp"&gt;&amp;lt;![CDATA[                
                public string GetFullPath(string databaseFileName)
                {
                    return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), "..", "Library", databaseFileName);
                }                        
                ]]&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/Code&amp;gt;&lt;/span&gt; 
            &lt;span class="nt"&gt;&amp;lt;Imports&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;Import&amp;gt;&lt;/span&gt;              
                  &lt;span class="nt"&gt;&amp;lt;Namespace&amp;gt;&lt;/span&gt;System.IO&lt;span class="nt"&gt;&amp;lt;/Namespace&amp;gt;&lt;/span&gt;
                &lt;span class="nt"&gt;&amp;lt;/Import&amp;gt;&lt;/span&gt;
            &lt;span class="nt"&gt;&amp;lt;/Imports&amp;gt;&lt;/span&gt;                     
        &lt;span class="nt"&gt;&amp;lt;/Snippet&amp;gt;&lt;/span&gt;        
    &lt;span class="nt"&gt;&amp;lt;/CodeSnippet&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/CodeSnippets&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Ya podemos utilizar el code snippet.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fosa61uqt4c61qkekfeul.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fosa61uqt4c61qkekfeul.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Presionamos la tecla TAB dos veces para comprobar el correcto funcionamiento de este code snippet.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffjxmklm8k8ybbftr4wl9.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffjxmklm8k8ybbftr4wl9.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; No olvidar implementar la interface creada en el proyecto .NET Standard y exportar el assembly &lt;strong&gt;[assembly: Dependency(typeof(ConfigDataBase))]&lt;/strong&gt; sobre la línea del namespace de cada implementación, puedes crear un code snippet para esto si lo requieres aunque yo lo considero innecesario. &lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Los Code Snippet son útiles para ser más productivos ya que nos permiten encapsular bloques de código que usamos muy a menudo y reutilizarlo mediante un comando de menú contextual o una combinación de teclas de acceso rápido. &lt;/p&gt;

&lt;p&gt;Puedes crear Code Snippet para Visual Studio for Mac en el siguiente link:&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/visualstudio/mac/snippets?view=vsmac-2019" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/visualstudio/mac/snippets?view=vsmac-2019&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para Windows utiliza el siguiente link:&lt;br&gt;
&lt;a href="https://docs.microsoft.com/es-es/visualstudio/ide/walkthrough-creating-a-code-snippet?view=vs-2019" rel="noopener noreferrer"&gt;https://docs.microsoft.com/es-es/visualstudio/ide/walkthrough-creating-a-code-snippet?view=vs-2019&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;En el siguiente Link encontrarás los archivos creados en este post&lt;/strong&gt;&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/EbarriosCode" rel="noopener noreferrer"&gt;
        EbarriosCode
      &lt;/a&gt; / &lt;a href="https://github.com/EbarriosCode/CodeSnippetsEFCoreXamarinForms" rel="noopener noreferrer"&gt;
        CodeSnippetsEFCoreXamarinForms
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>xamarin</category>
      <category>efcore</category>
      <category>dotnet</category>
      <category>mobile</category>
    </item>
    <item>
      <title>¿Qué demonios es Docker y Docker-Compose? y cómo Dockerizar Dotnet Core WebApi y SQL Server en un ambiente de desarrollo ideal</title>
      <dc:creator>Eduardo Barrios</dc:creator>
      <pubDate>Mon, 15 Jun 2020 00:55:12 +0000</pubDate>
      <link>https://forem.com/ebarrioscode/que-demonios-es-docker-docker-compose-y-como-dockerizar-dotnet-core-webapi-y-sql-server-en-un-ambiente-de-desarrollo-ideal-95a</link>
      <guid>https://forem.com/ebarrioscode/que-demonios-es-docker-docker-compose-y-como-dockerizar-dotnet-core-webapi-y-sql-server-en-un-ambiente-de-desarrollo-ideal-95a</guid>
      <description>&lt;p&gt;A menudo que avanzamos en esta extensa curva de aprendizaje en el mundo de la ingeniería y desarrollo de software, nos encontramos con problemas que debemos resolver, algunos muy típicos y otros no tanto. En este post me enfocaré en abordar algunos problemas relacionados al ciclo de vida del desarrollo del software como:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;¿Por qué nadie usa la versión estable de DotNet? - &lt;strong&gt;El arquitecto&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;En mi máquina funcionaba. - &lt;strong&gt;El desarrollador&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Copie los archivos a donde dijiste, si no funciona es tu problema - &lt;strong&gt;Operaciones&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Vamos a centrarnos en una de las tantas tecnologías de moda en la industria del software llamada Docker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Que abordaremos en este post
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;¿Qué demonios es Docker?&lt;/li&gt;
&lt;li&gt;Máquinas Virtuales&lt;/li&gt;
&lt;li&gt;Contenedores de Docker&lt;/li&gt;
&lt;li&gt;Docker-Compose &lt;/li&gt;
&lt;li&gt;Utilizar Docker-Compose para crear un ambiente Multi-Contenedor con ASP.NET Core y SQL Server&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Requisitos
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Docker-Desktop&lt;/li&gt;
&lt;li&gt;Visual Studio 2019&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F74jl7m7yta7v91ivkooq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F74jl7m7yta7v91ivkooq.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Docker
&lt;/h1&gt;

&lt;p&gt;Una plataforma abierta para desarrollar, enviar y ejecutar aplicaciones que te permite empaquetar tu proyecto con todas sus dependencias únicamente necesarias en un simple binario, de forma totalmente aislada al resto de aplicaciones que puedan convivir en el mismo host. &lt;br&gt;
Docker es muy útil para desarrolladores y administradores de sistemas para compilar, ejecutar y compartir aplicaciones en contenedores. &lt;br&gt;
Los contenedores no son nuevos el concepto data desde 1979 y aunque Docker como tal salió en 2013 hoy en día sigue siendo tendencia y su uso para implementar fácilmente aplicaciones es totalmente genial.&lt;br&gt;
El concepto de utilizar contenedores es cada vez más popular debido a que nos ofrecen múltiples beneficios y características como las siguientes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Flexibles:&lt;/strong&gt; Incluso las aplicaciones más complejas se pueden contenerizar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Ligeros:&lt;/strong&gt; Los contenedores aprovechan y comparten el Kernel del host, haciéndolos mucho más eficientes en términos de recursos del sistema que las máquinas virtuales.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Portables:&lt;/strong&gt; Puedes compilar localmente, implementar en la nube y ejecutar en cualquier lugar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Acoplados holgadamente:&lt;/strong&gt; Los contenedores son altamente autosuficientes y encapsulados, lo que te permite reemplazar o actualizar uno sin interrumpir a otros.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Escalables:&lt;/strong&gt; Puedes aumentar y distribuir automáticamente réplicas de contenedor en un centro de datos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Seguros:&lt;/strong&gt; Los contenedores aplican restricciones y aislamientos agresivos a los procesos sin ninguna configuración necesaria por parte del usuario.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Los contenedores y las máquinas virtuales a menudo son muy comparados debido a que son tecnologías que nos ofrecen un mecanismo de virtualización, aunque nos pueden servir para lo mismo presentan algunas notables diferencias, analicemos cada uno por separado y al final tendremos una conclusión sobre un contenedor versus una máquina virtual.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  &lt;em&gt;Máquinas Virtuales (VM)&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Una VM nos provee de un sistema operativo completo funcionando de manera aislada sobre otro sistema operativo completo.&lt;br&gt;
La tecnología de VMs permite compartir hardware entre varios sistemas operativos al mismo tiempo.&lt;br&gt;
A continuación un esquema simplificado de arquitectura de VMs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqaoc2bmxqd3bmi41limo.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fqaoc2bmxqd3bmi41limo.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Léelo de abajo a arriba&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Es lógico pensar que tras bambalinas siempre tiene que existir infraestructura que lo soporte todo, esta puede ser tu computadora personal para desarrollo, un servidor onpremise en tu data center o algún servicio de infraestructura en la nube IaaS que ofrecen distintos proveedores como Azure, AWS, Google Cloud, Digital Ocean, etc, para esto existen múltiples opciones pero al final se trata siempre de "infraestructura": máquinas físicas sobre las que se ejecutan las VMs.&lt;br&gt;
No obstante para que las máquinas virtuales puedan ejecutarse es necesario otro componente importante que está por encima del S.O. llamado hipervisor, un software especializado para exponer los recursos de hardware del host, de modo que puedan ser utilizados por otros sistemas operativos, obviamente esto incluye CPUs, memoria, tarjeta de red, espacio de almacenamiento en disco y el resto del hardware. &lt;br&gt;
En conclusión la tarea del hypervisor es engañar a un sistema operativo convencional para que crea que se está ejecutando sobre una máquina física. &lt;br&gt;
Los hipervisores que probablemente conozcas porque son muy comunes y son los que personalmente conozco:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VirtualBox&lt;/li&gt;
&lt;li&gt;Hyper-V &lt;/li&gt;
&lt;li&gt;VMWare&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  &lt;em&gt;Contenedores de Docker&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Los contenedores por su parte tienen un enfoque totalmente distinto al de las VMs. Si bien es cierto tratan también de aislar aplicaciones y de generar un entorno replicable, portable y estable para la ejecución de procesos, esto gracias a los namespaces y control groups de Linux.&lt;br&gt;
Los contenedores en lugar de ejecutar un sistema operativo completo lo que hacen es compartir los recursos del propio sistema operativo "host" sobre el que se ejecutan.&lt;/p&gt;

&lt;p&gt;A continuación el esquema equivalente al de VMs, para el caso de contenedores:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpj2klcqff58o8525jyel.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpj2klcqff58o8525jyel.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Visualmente podemos notar que solo desaparece la capa del sistema operativo huésped (Guest Host), y se sustituye el hipervisor por el motor de Docker, sin embargo las diferencias son grandes.&lt;br&gt;
Docker se encarga de ejecutar y gestionar los contenedores, pero en lugar de exponer los diferentes recursos de hardware del host, lo que hace es compartir entre todos los contenedores ese hardware, optimizando su uso y eliminando la necesidad de tener n cantidad de sistemas operativos separados para conseguir el aislamiento y garantizar el mismo comportamiento de las aplicaciones contenerizadas en diferentes ambientes.&lt;/p&gt;

&lt;p&gt;Otro tema muy importante sobre Docker es su funcionamiento con base en imágenes que se pueden reutilizar entre varias aplicaciones y/o contenedores. Cada una de esas imágenes se puede asimilar como una "capa" que se puede superponer a otras para formar un sistema de archivos que combina todas las capas necesarias.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Ejemplo:&lt;/strong&gt; Una capa puede contener las bibliotecas o el runtime que necesitamos utilizar, para este ejemplo será el SDK de Dotnet Core, otra con bibliotecas determinadas de las que hace uso nuestra aplicación por ejemplo Entity Framework, Serilog, JWT, etc, y otra capa final con el código fuente de nuestra aplicación. La combinación de todas estas capas nos da como resultado una nueva imagen, única de nuestra aplicación, y con esta nueva y única imagen podemos instanciar y crear uno o varios contenedores.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Nota Importante:&lt;/strong&gt; Las VMs y los contenedores son tecnologías que persiguen un fin similar, pero con distintos enfoques.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;
  
  
  Docker-Compose
&lt;/h1&gt;

&lt;p&gt;Es una herramienta para definir y ejecutar aplicaciones Docker multicontenedor que permite simplificar el uso de Docker a partir de archivos YAML, de está forma es mas sencillo crear contendores que se relacionen entre sí, conectarlos, habilitar puertos, volumenes, etc. Nos permite lanzar un solo comando para crear e iniciar todos los servicios desde su configuración(YAML), esto significa que puedes crear diferentes contenedores y al mismo tiempo diferentes servicios en cada contenedor, integrarlos a un volumen común e iniciarlos y/o apagarlos, etc. Este es un componente fundamental para poder construir aplicaciones y microservicios.&lt;br&gt;
Docker-Compose funciona en todos los entornos:  production, staging, development, testing, así como flujos de trabajo basados en Continuous Integration(CI).&lt;br&gt;
Si quieres conocer más acerca de Docker-Compose ve a la documentación oficial &lt;a href="https://docs.docker.com/compose/#features" rel="noopener noreferrer"&gt;https://docs.docker.com/compose/#features&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; En este Post utilizaremos docker-compose para lanzar dos contenedores. Uno que contenga todas las dependencias para empaquetar una solución ASP.NET Core WebApi y otro contenedor que contenga las dependencias necesarias para nuestra Base de Datos SQL Server. Mediante docker-compose haremos el enlace de comunicación entre ambos contenedores.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Estoy seguro que hasta este punto ya entendemos lo básico de cómo funcionan ambas tecnologías.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4ibvujpmazv4g24t3bkq.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4ibvujpmazv4g24t3bkq.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Vamos a centrarnos en crear un entorno ideal de desarrollo con tecnologías Microsoft (Dotnet Core y SQL Server) sobre Docker aprovechando la facilidad que nos proporciona docker-compose sobre el Engine de Docker para realizar tareas programáticamente.&lt;/p&gt;
&lt;h2&gt;
  
  
  Utilizando Docker-Compose para crear un ambiente Multi-Contenedor con ASP.NET Core y SQL Server
&lt;/h2&gt;

&lt;p&gt;Inicialmente vamos a necesitar una solución ASP.NET Core que vamos a empaquetar en un contenedor de docker, utilizaremos la siguiente solución perteneciente a un Post anterior.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/ebarrioscode" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F266312%2F64e4f515-0a74-4eb0-8ac4-76678329e64e.jpg" alt="ebarrioscode"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/ebarrioscode/base-de-datos-en-memoria-con-asp-net-core-3-0-mvc-entity-framework-core-3950" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Base de Datos en memoria con ASP.NET Core 3.0 MVC + Entity Framework Core&lt;/h2&gt;
      &lt;h3&gt;Eduardo Barrios ・ Nov 7 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#csharp&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#dotnet&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#database&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Esta solución utiliza una base de datos SQL Server In Memory, en este caso cambiaremos esa característica y vamos a montar SQL Server en un Contenedor de Docker.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Una vez que hemos abierto nuestra solución WebApi en Visual Studio 2019, vamos a situarnos en el proyecto WebApi y vamos a agregar la Compatibilidad con el Orquestador de Contenedores.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fptuk6viqv8ucxmthriep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fptuk6viqv8ucxmthriep.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Seleccionamos Docker-Compose&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5ryu6y5b52e6wuinqb7q.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F5ryu6y5b52e6wuinqb7q.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Tras pulsar el botón Aceptar empezará el proceso de creación del proyecto Docker-Compose en nuestra solución de Visual Studio, se agregará un archivo llamado Dockerfile en el proyecto WebApi y en segundo plano se hará pull de las imágenes de Docker necesarias para empaquetar nuestra solución.&lt;/p&gt;

&lt;p&gt;Examinaremos el nuevo proyecto Docker-Compose recientemente creado.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpccqmb7f6z0ak2h757ri.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fpccqmb7f6z0ak2h757ri.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Este proyecto consta de 3 archivos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;.dockerignore&lt;/strong&gt; - Se encarga de ignorar configuraciones o compilados y files que utiliza o crea Docker en tiempo de compilación y/o ejecución que son propios de cada ambiente y que no son necesarios al momento de hacer push al registry de Docker para publicar una imagen, el .dockerignore es similar al uso del .gitignore de repositorios Git.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsi0a2myw9kav9b7gnfp7.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsi0a2myw9kav9b7gnfp7.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;docker-compose.yml&lt;/strong&gt; - Es un archivo YAML donde definimos los servicios, redes, volumes y todo lo necesario para crear un ambiente con base en contenedores. Se encarga de buscar instrucciones para ejecutarlas, estas instrucciones contienen toda la configuración que será aplicada a cada contenedor iniciado por ese servicio. &lt;br&gt;
Las instrucciones del docker-compose.yml son equivalentes a pasarle parámetros al comando &lt;strong&gt;docker run&lt;/strong&gt;, de la misma manera las definiciones de las redes y volumes serían semejantes a los comandos &lt;strong&gt;docker network create&lt;/strong&gt; y &lt;strong&gt;docker volume create&lt;/strong&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fewpmnjd1n1vi3h0m3q5j.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fewpmnjd1n1vi3h0m3q5j.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;A continuación una descripción simple de las principales instrucciones contenidas en el archivo docker-compose.yml&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;version:&lt;/strong&gt; Los archivos docker-compose.yml son versionados y es importante indicar la versión a utilizar.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;services:&lt;/strong&gt; Indica los servicios a utilizar, podemos anidar n cantidad de servicios a esta instrucción, cada servicio puede tener cualquier nombre pero como buena práctica lo mejor es dar nombres explícitos. Para nuestro ejemplo utilizaremos dos servicios que representan un WebApi de dotnet core y una base de datos Sql Server. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;dockerizingwebapi:&lt;/strong&gt; Es el nombre de nuestro primer servicio y hace referencia a nuestro WebApi.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;container_name:&lt;/strong&gt; Permite establecer un nombre para un contenedor al que hace referencia el servicio.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;image:&lt;/strong&gt; Permite tagear la imagen que se creará para instanciar el contenedor en el que estará montado el servicio. Es equivalente a utilizar el comando &lt;strong&gt;docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;build:&lt;/strong&gt; Se utilizar para indicar el contexto e indicar la ruta del archivo Dockerfile para construir el contenedor del servicio. Posteriormente veremos que es un Dockerfile.      &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;depends_on:&lt;/strong&gt; Se utiliza para establecer la dependencia y comunicación con otros servicios, en este caso el servicio dockerizingwebapi necesita comunicarse con el servicio database que se encuentra definido posteriormente.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;database:&lt;/strong&gt; Es el nombre de nuestro segundo servicio y hace referencia a la base de datos sql server.    &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;ports:&lt;/strong&gt; Se utiliza para exponer los puertos necesarios desde el contenedor.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;environment:&lt;/strong&gt; Permite establecer variables de entorno durante el ciclo de vida del contenedor.&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;docker-compose.override.yml&lt;/strong&gt; - Expone configuraciones específicas para el entorno de desarrollo. Crea algunas variables de entorno, expone algunos puertos del host y monta algunos volumes.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fweti2kwwnc96cber49ql.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fweti2kwwnc96cber49ql.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Docker-Compose nos permite utilizar múltiples archivos de configuración y personalizar nuestra aplicación con base en Compose para diferentes ambientes o flujos de trabajo con el fin de compartir configuración común.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Ejemplo:&lt;/strong&gt; Podríamos crear un archivo &lt;strong&gt;docker-compose.prod.yml&lt;/strong&gt; y que exponga configuraciones específicas para un entorno productivo. Lo mismo podríamos hacer con otros ambientes como Staging, Testing, Production, etc. Con esto podemos aprovechar extender esta funcionalidad para replicar entornos y que cada entorno contenga configuraciones propias.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Dockerfile
&lt;/h2&gt;

&lt;p&gt;Para crear contenedores de Docker podemos utilizar varios comandos, descargar imágenes del Registry de Docker con &lt;strong&gt;docker pull&lt;/strong&gt; seguidamente utilizar &lt;strong&gt;docker run&lt;/strong&gt;, y múltiples acciones que podemos realizar con más comandos de Docker. &lt;br&gt;
Un Dockerfile es un archivo de texto plano que contiene todos los comandos de Docker que podríamos ejecutar desde la línea de comandos para crear una imagen y seguidamente instanciar un contenedor con base en esa imagen. Docker nos permite construir imágenes automáticamente ejecutando las instrucciones definidas en un Dockerfile.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg0tpoq9z5g7b4t924qca.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fg0tpoq9z5g7b4t924qca.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; El Dockerfile que crea la plantilla de Visual Studio por defecto viene preparado con multi-stage-builds para poder declarar múltiples &lt;strong&gt;FROM&lt;/strong&gt; en el archivo Dockerfile y garantizar una adecuada optimización de nuestra imagen final de Docker, de esta manera tendremos una imagen limpia con base en otras imágenes de Docker.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Podemos observar que en segundo plano se está haciendo un pull de las imágenes definidas en las instrucciones &lt;strong&gt;FROM&lt;/strong&gt; del Dockerfile, esto hace referencia a dos imágenes de los repositorios de Microsoft. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftjot8ln43bin4p05pazp.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftjot8ln43bin4p05pazp.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Ahora crearemos las migraciones para poder crear la estructura de la base de datos dentro del contenedor e inicializar las tablas de la base de datos, para esto tendremos que ejecutar migraciones como lo hacemos normalmente en la consola de administración de paquetes nuget.&lt;br&gt;
Seleccionamos el proyecto WebApi como proyecto de inicio y ejecutamos el comando &lt;strong&gt;Add-Migration&lt;/strong&gt; [nombre_de_la_migración]. Lo anterior creará el Directorio Migrations y las migraciones representadas como clases C#.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjcg525ylbbv5ayctgr55.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjcg525ylbbv5ayctgr55.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Crearemos una clase static y la nombraremos DbInitializer.cs. Esta clase tendrá un método static que recibe como parámetro el contexto de datos que utilizaremos para crear datos iniciales posteriormente a crear las tablas.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3ed5shaeulgxkd1hvd8l.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3ed5shaeulgxkd1hvd8l.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzraxeiug6unbzv7np2cc.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzraxeiug6unbzv7np2cc.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Debemos volver a seleccionar como proyecto de inicio Docker-Compose ya que en este caso no haremos un &lt;strong&gt;Update-Database&lt;/strong&gt; en la consola de administración de paquetes de Nuget de VS, a continuación definiremos un método en la clase Startup.cs que haga esa tarea automáticamente.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Llamaremos a este método UpdateDatabase, lo utilizaremos para aplicar las migraciones en el contenedor y crear datos de inicio en las tablas correspondientes a nuestros modelos en la base de datos dentro del contenedor.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkq20et07q2d5jzotilyu.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkq20et07q2d5jzotilyu.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Invocaremos al método anterior en el método Configure() de la misma clase Startup.cs.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiat4kyxb6fzk8e1vzrg6.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fiat4kyxb6fzk8e1vzrg6.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Ahora modificaremos la implementación de la inyección de la dependencia de nuestro contexto de datos Entity Framework Core. Reemplazaremos el método UseInMemmoryDatabase por el método UseSqlServer, le pasaremos la cadena de conexión definida en el archivo appsettings.json y haremos un Replace pasando el valor de un EndPoint definido como variable de entorno del contenedor en el archivo docker-compose.override.yml.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw4qpb30wnx6pn2dvxcew.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fw4qpb30wnx6pn2dvxcew.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fq3wv9o1e655atsg2527e.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fq3wv9o1e655atsg2527e.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Todo está listo es hora de probar, vamos a seleccionar nuestro proyecto Docker-Compose como proyecto de inicio, seguidamente ejecutamos la solución desde Visual Studio. Notaremos que Visual Studio se encarga de lanzar los comandos de Docker y Docker-Compose para utilizar todas las configuraciones.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fog5qln0vccrar4ovywqs.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fog5qln0vccrar4ovywqs.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Ahora iremos a Postman y lanzamos una petición HTTP Get a la url api/Albumes.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmd44penev96dj3tiu05x.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmd44penev96dj3tiu05x.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzwaqgzujh6co9d4mm63m.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzwaqgzujh6co9d4mm63m.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Podemos aprovechar las herramientas que nos provee Visual Studio 2019 para obtener información sobre nuestros contenedores.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7al4nhrkgvulvyetjovw.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7al4nhrkgvulvyetjovw.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Como puedes notar en contenedores de Solución tenemos dos contenedores, el primero que contiene un WebApi y el siguiente una Base de datos Sql Server.&lt;/p&gt;


&lt;/blockquote&gt;

&lt;p&gt;También podemos obtener información de nuestros contenedores que están en ejecución lanzando el comando &lt;strong&gt;docker ps&lt;/strong&gt; en cualquier terminal, utilizaré PowerShell.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz2snw185ozuc9arz0xwo.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz2snw185ozuc9arz0xwo.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Con docker ps obtendremos información de contenedores en ejecución, información como el ID de cada Contenedor, la imagen que utilizó cada contenedor para crearse, los puertos que expone cada contendor.&lt;/p&gt;


&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Conclusiones&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Contenedores VS Máquinas Virtuales: Sus diferencias son enormes, tanto en la teoría como en la práctica y es que los contenedores comparten el mismo sistema operativo con el host, conteniendo solo lo estrictamente necesario para ejecutar una Aplicación, Base de Datos, Web Service, un Sistema Operativo, lo que sea que tu quieras empaquetar dentro de un contenedor, mientras que las máquinas virtuales incorporan un sistema operativo completo. Esto afecta directamente y enormemente el rendimiento: al haber menos capas entre el metal (infraestructura) y la aplicación; se ganan milisegundos de latencia preciada. El tiempo de arranque de un contenedor Docker es increíblemente instantáneo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Los contenedores permiten desplegar aplicaciones rápidamente, arrancarlas, detenerlas más rápido y aprovechar mejor los recursos de hardware. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;En cuanto a la utilización de Docker con tecnologías .NET, Visual Studio nos ayuda a ser ágiles en muchos aspectos. Todo lo realizado en este Post puedes hacerlo sin Visual Studio, lanzando los comandos de Docker en cualquier terminal como PowerShell, CMD, Git bash, etc y utilizando cualquier editor de código para modificar tus archivos.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;La función principal de Docker-Compose es la creación de infraestructura basada en microservicios, es decir, los contenedores y los vínculos entre ellos. No obstante esta herramienta es capaz de hacer mucho más, como: &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Crear Imágenes, si está definido en el Dockerfile&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

docker-compose build


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Escalar contenedores de forma sencilla&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

docker-compose scale SERVICE=5


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;em&gt;Se pueden volver a ejecutar los contenedores que se han detenido&lt;/em&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

docker-compose up --no-recreate


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Docker nos ayuda a crear imágenes y contenedores para nuestras aplicaciones y poder ser más eficientes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;En fin hemos visto y definido qué es y para que nos ayuda Docker y Docker-Compose, la importancia que tiene hoy en día para la implementación de infraestructuras simples que pueden ser para ambientes de desarrollo u otras más complejas que necesitan de alguna forma rápida poder crecer y ser escalables sin que se tengan que hacer tantos procesos manuales.&lt;/p&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Link al respositorio en GitHub&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev.to%2Fassets%2Fgithub-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/EbarriosCode" rel="noopener noreferrer"&gt;
        EbarriosCode
      &lt;/a&gt; / &lt;a href="https://github.com/EbarriosCode/Docker-Compose-DevEnvironment-WebApi_3.1-with-SQLServer" rel="noopener noreferrer"&gt;
        Docker-Compose-DevEnvironment-WebApi_3.1-with-SQLServer
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Guía de explicación sobre este repositorio https://dev.to/ebarrioscode/que-demonios-es-docker-docker-compose-y-como-dockerizar-dotnet-core-webapi-y-sql-server-en-un-ambiente-de-desarrollo-ideal-95a
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Referencias&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/get-started/overview/" rel="noopener noreferrer"&gt;https://docs.docker.com/get-started/overview/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.microsoft.com/en-us/virtualization/windowscontainers/about/containers-vs-vm" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/virtualization/windowscontainers/about/containers-vs-vm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/compose/extends/" rel="noopener noreferrer"&gt;https://docs.docker.com/compose/extends/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.docker.com/compose/aspnet-mssql-compose/" rel="noopener noreferrer"&gt;https://docs.docker.com/compose/aspnet-mssql-compose/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>docker</category>
      <category>dotnet</category>
      <category>containers</category>
      <category>csharp</category>
    </item>
    <item>
      <title>Azure Functions (Serverless) + Entity Framework Core y SQL Azure</title>
      <dc:creator>Eduardo Barrios</dc:creator>
      <pubDate>Sat, 16 May 2020 22:48:39 +0000</pubDate>
      <link>https://forem.com/ebarrioscode/azure-functions-serverless-entity-framework-core-y-sql-azure-1ngd</link>
      <guid>https://forem.com/ebarrioscode/azure-functions-serverless-entity-framework-core-y-sql-azure-1ngd</guid>
      <description>&lt;p&gt;Azure Functions es una solución Serverless en la nube de Microsoft Azure muy útil y práctica de usar en la actualidad. Por otro lado desarrollar una Function que requiere funcionalidades relacionadas al acceso a datos es obvio que los desarrolladores .NET nos preguntamos en algún momento ¿puedo usar mi ORM favorito Entity Framework Core para acceder a los datos de una Base de Datos SQL Server o SQL Azure desde una Azure Function? &lt;br&gt;
Obviamente la respuesta es Sí, claro que es posible, Microsoft anunció en el Build del año pasado la compatibilidad entre la inserción de dependencias en Azure Functions, esto significa que puede registrarse y utilizar sus propios servicios como parte de las funciones. &lt;br&gt;
Aunque antes de esto ha sido posible utilizar Entity Framework Core en el pasado, la diferencia es que ahora el emparejamiento con la inserción de dependencias ha sido convertido a un ajuste mucho más natural. &lt;br&gt;
Obviamente esto se vuelve más interesante con la llegada de Azure Functions V3 que desde Enero de este año está disponible de manera general, esto significa que ahora es posible compilar e implementar funciones con la versión en tiempo de ejecución 3.0 en producción. Esta nueva versión de Azure Functions ofrece nuevas capacidades, incluida la capacidad de tener como destino .NET Core 3.1 &lt;br&gt;
También es altamente compatible con versiones anteriores, por lo que la mayoría de las aplicaciones existentes que se ejecutan en versiones anteriores deben ser capaces de actualizar a la versión 3 y ejecutarse sin ningún cambio en el código.&lt;/p&gt;
&lt;h2&gt;
  
  
  Que abordaremos en este post
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Creación de una Azure Function V3 localmente&lt;/li&gt;
&lt;li&gt;Integración de EF Core con Azure Function&lt;/li&gt;
&lt;li&gt;Inyección de Dependencias&lt;/li&gt;
&lt;li&gt;Migraciones con EF Core y Actualización de Base de Datos&lt;/li&gt;
&lt;li&gt;Acceder a datos alojados en SQL Azure&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  Requisitos
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Suscripción de Azure, si no tienes una obtiene una aquí &lt;a href="https://azure.microsoft.com/es-es/free/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/es-es/free/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;DotNet Core 3.1 SDK&lt;/li&gt;
&lt;li&gt;Visual Studio 2019&lt;/li&gt;
&lt;li&gt;Azure Function Core Tools Versión 3&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;h1&gt;
  
  
  Creando Azure Function
&lt;/h1&gt;

&lt;p&gt;Vamos a crear un proyecto Azure Functions V3 desde Visual Studio 2019 para poder ejecutarla localmente desde nuestra máquina de desarrollo.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffircqafmpgyf41kjleci.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ffircqafmpgyf41kjleci.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Seguidamente vamos a crear la estructura de directorios en la solución.&lt;br&gt;
Quedaría de la siguiente manera:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6me8lf5ug6mpj5qq05wv.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6me8lf5ug6mpj5qq05wv.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; La plantilla de una solución de Azure Function en Visual Studio crea por defecto una clase llamada Function1.cs modificaremos ese nombre por FunctionEFCore.cs, también puedes notar que existe una clase Startup.cs pero no te preocupes explicaré el porqué existe esta clase en esta solución.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h1&gt;
  
  
  Integración de EF Core con Azure Function
&lt;/h1&gt;

&lt;p&gt;Debemos instalar los paquetes Nuget necesarios para utilizar Entity Framework Core.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcjx291g9z6w48dvxz7j2.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fcjx291g9z6w48dvxz7j2.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Microsoft.EntityFrameworkCore.SqlServer es el proveedor de base de datos de Microsoft SQL Server para Entity Framework Core y permite la manipulación de bases de datos mediante el ORM.&lt;br&gt;
Microsoft.EntityFramewrokCore.Tools contiene las herramientas principales de Entity Framework para la consola del Administrador de paquetes NuGet en Visual Studio y habilita los comandos de uso común como: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Add-Migration &lt;/li&gt;
&lt;li&gt;Drop-Database &lt;/li&gt;
&lt;li&gt;Get-DbContext &lt;/li&gt;
&lt;li&gt;Scaffold-DbContext &lt;/li&gt;
&lt;li&gt;Script-Migrations &lt;/li&gt;
&lt;li&gt;Update-Database&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ahora crearemos los modelos, utilizaré los modelos de Album y Artista que he utilizado en posts anteriores, si has leído alguno seguramente se te harán familiares.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkng9wz6np3hsgfm29uru.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkng9wz6np3hsgfm29uru.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi8k8cqbqcug07padpude.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fi8k8cqbqcug07padpude.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Escribiremos el contexto de datos y agregaremos los modelos correspondientes como propiedades DbSet.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhbuns71rnswvi7po9hs4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhbuns71rnswvi7po9hs4.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F54tfsa9e90cvwml7tdl7.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F54tfsa9e90cvwml7tdl7.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; En este contexto hice un override del método OnModelCreating() para poder crear datos iniciales al momento de crear las migraciones, ejecutar el comando Update-Database y sincronizar la base de datos SQL Azure. Esto creará las tablas en la BD y seguidamente realizará múltiples insert para crear registros.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Previo a correr los comandos para crear las migraciones y hacer un update a nuestra base de datos habilitaremos la creación del DbContext en tiempo de diseño, ya que necesitamos crear una instancia derivada de DbContext. &lt;br&gt;
Para esto implementaremos la interface IDesignTimeDbContextFactory para habilitar los servicios en tiempo de diseño y para este caso en particular las migraciones. Esto aplica únicamente para los tipos de contexto que no tienen un constructor predeterminado público, recordemos que esta no es una solución ASP.NET por eso es necesario. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmcoqkhsd7dr2rge8w62t.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmcoqkhsd7dr2rge8w62t.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;Seguidamente un paso muy importante es obtener el .dll de la solución en el lugar correcto. Al compilar un proyecto de Azure Functions se organizan algunos artefactos de compilación para crear una estructura de proyecto de function válida, en este proceso el .dll de la solución se mueve a una subcarpeta. Desafortunadamente para las herramientas en tiempo de diseño como las migraciones, esperan que el archivo .dll esté en la raíz del destino de compilación pero esto no sucede así y para resolverlo tendremos que hacer una copia del .dll de la solución a la raíz del proyecto. &lt;br&gt;
Vamos a modificar el archivo .csproj y agregaremos un evento posterior a la compilación para copiar el archivo .dll en la raíz de la solución.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjdlztilxp6d53s30g1as.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjdlztilxp6d53s30g1as.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;


&lt;h1&gt;
  
  
  Inyección de Dependencias
&lt;/h1&gt;

&lt;p&gt;Para hacer uso de Inyección de Dependencias (DI) en Azure Function al igual que en una solución de ASP.NET necesitamos acceder al Contenedor de Inversión de control para lograr una inicialización de nuestros servicios.&lt;br&gt;
La plantilla de una solución Azure Function en Visual Studio no incluye una clase Startup.cs por lo que debemos agregarla.&lt;br&gt;
Si no sabes que es Inyección de Dependencias o quieres conocer más detalles y como funciona este patrón de diseño de software te recomiendo leas este post.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag__link"&gt;
  &lt;a href="/ebarrioscode" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F266312%2F64e4f515-0a74-4eb0-8ac4-76678329e64e.jpg" alt="ebarrioscode"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/ebarrioscode/inyeccion-de-dependencias-di-en-asp-net-core-mejores-practicas-para-escribir-codigo-reutilizable-escalable-y-desacoplado-kho" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Inyección de Dependencias(DI) en ASP.NET Core, mejores prácticas para escribir código reutilizable, escalable y desacoplado&lt;/h2&gt;
      &lt;h3&gt;Eduardo Barrios ・ Nov 16 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#dotnet&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#csharp&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#webdev&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;





&lt;p&gt;Aquí es donde sucede la magia de Inyección de Dependencias. La clase Startup.cs configura los servicios y la canalización de solicitudes de la aplicación además de controlar el Contenedor de Inversión de Controles (IoC) encargado de proveer las instancias de los tipos los cuales le decimos en el inicio de la Aplicación (Startup).&lt;br&gt;
En este punto le dejaremos la responsabilidad de instanciar e inicializar nuestras dependencias tales como el Contexto de Datos y los diferentes servicios específicos de cada tipo de objeto que necesitemos a lo largo del desarrollo de este software.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2l1a1b74q76pyu1txkbd.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F2l1a1b74q76pyu1txkbd.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;El Método Configure(IFunctionsHostBuilder builder) es donde registramos todos los servicios. IFunctionHostBuilder.Services es el contenedor IoC.&lt;/li&gt;
&lt;li&gt;Registrar servicios es exactamente lo mismo que con ASP.NET Core, mediante el uso de los métodos AddScoped, AddSingleton, AddTransient.&lt;/li&gt;
&lt;li&gt;La clase Startup debe extender de FunctionsStartup.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Necesitaremos un Servicio de Albumes el cuál tendrá delegadas todas las responsabilidades de manipulación de datos que tengan que ver con objetos tipo Album, este servicio utiliza como dependencia el DbContext, solo debemos preocuparnos por inyectarlo, recordemos que IoC se encargará de instanciarlo e inicializarlo.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1zlovh3sjmx8ldu7pgvs.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F1zlovh3sjmx8ldu7pgvs.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Base de Datos SQL Azure
&lt;/h3&gt;

&lt;p&gt;Necesitamos una base de datos de Azure, para esta práctica ya tengo creada una BD en Azure.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjjhfjf1xrtt7rifujep7.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjjhfjf1xrtt7rifujep7.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Migraciones con EF Core y Actualización de Base de Datos
&lt;/h1&gt;

&lt;p&gt;Antes de iniciar con los comandos para correr las migraciones y hacer el update a la base de datos remota alojada en Azure, debemos establecer una cadena de conexión que sea accesible en tiempo de diseño. Para esto utilizaremos una variable de entorno y correremos el siguiente comando en la consola de administración de paquetes nuget de Visual Studio.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;$env:SqlConnectionString="Server={Nombre o IP del Servidor};Initial Catalog={Nombre de la BD};Persist Security Info=False;UserID={UserSQL};Password={Password};MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ahora debemos correr el comando Add-Migration [Nombre_de_la_migracion] yo le llamaré Initial_Model.&lt;br&gt;
Esta migración creará las instrucciones necesarias para crear las tablas en la bd con base en los modelos que tenemos registrados en el Contexto de Datos y posteriormente insertar datos iniciales, a esta técnica se le denomina Code First.&lt;br&gt;
Tras una ejecución con éxito podremos notar que se agregó un directorio llamado Migrations en la la raíz del proyecto, este directorio contiene las migraciones creadas representadas como clases C#.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhenwa8dxk6dee5g5mko7.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fhenwa8dxk6dee5g5mko7.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Debemos utilizar la migración que acabamos de crear para que los cambios se vean reflejados en la bd, para eso correremos el comando Update-Database.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftqrfm5va4e5w565hovqd.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Ftqrfm5va4e5w565hovqd.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Para ver los cambios reflejados en la bd vamos a conectarnos mediante Azure Data Studio, únicamente necesitamos el nombre del servidor, un usuario y contraseña para acceder, esto lo encuentras en la administración de la base de datos en el portal de Azure o puedes revisar la cadena de conexión que utilizamos al setear la variable de entorno y que obviamente se obtuvo en el portal de Azure.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fitp1gn0xk85q8xm2bhxl.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fitp1gn0xk85q8xm2bhxl.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Ya podemos ver las tablas creadas en la base de datos y corresponden a los modelos Album y Artista establecidos en nuestra solución.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ejecutamos dos instrucciones SQL para verificar la existencia de datos que definimos en el método OnModelCreating() en la clase Contexto de Datos.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyo754t5mb5779xvuhwud.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyo754t5mb5779xvuhwud.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h1&gt;
  
  
  Acceder a datos alojados en SQL Azure
&lt;/h1&gt;

&lt;p&gt;Ahora lo que debemos hacer es modificar el código en la clase principal FunctionEFCore.cs para utilizar el servicio de Albumes pero para utilizar ese servicio debemos inyectar la dependencia en el método constructor de la clase FunctionEFCore.cs. &lt;br&gt;
Eliminamos el código que crea por defecto la plantilla, eliminamos el static de la clase y el método, invocamos el método GetAsync del Servicio de Albumes y le enviamos ese objeto resultado a una nueva instancia de OkObjectResult que será el resultado a retornar de nuestra Azure Function.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fusw9n5fksc6hykcnv57b.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fusw9n5fksc6hykcnv57b.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Probaremos localmente nuestra function, posterior a compilar y ejecutar esta solución, vamos a PostMan y enviamos una solicitud Http GET.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8ikcz1y9z1xh6f5785mu.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F8ikcz1y9z1xh6f5785mu.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Funciona correctamente, el resultado es el esperado.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Conclusión&lt;/strong&gt; &lt;br&gt;
Esta nueva característica de inserción de dependencias en Azure Functions facilita el trabajo con contextos de base de datos de Entity Framework Core, esto nos da la facilidad de montar un backend en un ambiente de development, test, stage, o production en poco tiempo basándonos en las soluciones Serverless.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Link al Repositorio en Github&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/EbarriosCode/AzureFunctionV3_EfCore.git" rel="noopener noreferrer"&gt;https://github.com/EbarriosCode/AzureFunctionV3_EfCore.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Referencias&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/azure-functions/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://devblogs.microsoft.com/dotnet/announcing-ef-core-3-0-and-ef-6-3-general-availability/" rel="noopener noreferrer"&gt;https://devblogs.microsoft.com/dotnet/announcing-ef-core-3-0-and-ef-6-3-general-availability/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/ef/core/" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/ef/core/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/azure-functions/functions-dotnet-dependency-injection&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>sql</category>
      <category>efcore</category>
      <category>azure</category>
    </item>
    <item>
      <title>Xamarin Forms + Azure Function, desarrollo acelerado y simplificando de aplicaciones Serverless</title>
      <dc:creator>Eduardo Barrios</dc:creator>
      <pubDate>Mon, 09 Mar 2020 02:48:18 +0000</pubDate>
      <link>https://forem.com/ebarrioscode/conectando-apps-moviles-xamarin-forms-con-azure-function-desarrollo-acelerado-y-simplificando-de-aplicaciones-serverless-n41</link>
      <guid>https://forem.com/ebarrioscode/conectando-apps-moviles-xamarin-forms-con-azure-function-desarrollo-acelerado-y-simplificando-de-aplicaciones-serverless-n41</guid>
      <description>&lt;p&gt;Constantemente en el mundo del desarrollo móvil las apps se conectan a un backend y naturalmente pensamos en una aplicación completa y la infraestructura para ejecutarla, pero que sucede en casos en los que no se necesita de una gran API o Servicio Web, optar por el ciclo natural podría volverse tedioso y trabajoso, para abordar esta problemática Microsoft nos ofrece el servicio en la nube denominado Azure Functions (Serverless). &lt;br&gt;
Serverless hace referencia a computación sin servidor, un modelo de ejecución en el que el proveedor en la nube en este caso (Azure) es responsable de ejecutar un fragmento de código mediante la asignación dinámica de los recursos. Y cobrando solo por la cantidad de recursos utilizados para ejecutar el código. El código generalmente, se ejecuta dentro de contenedores sin estado que pueden ser activados por una variedad de eventos que incluyen solicitudes HTTP, eventos de base de datos, servicios de colas, alertas de monitoreo, carga de archivos, eventos programados (trabajos cron), etc. El código que se envía al proveedor en la nube para la ejecución es generalmente en forma de una función. Por lo tanto, serverless se denomina “Funciones como servicio” o “FaaS”.&lt;/p&gt;

&lt;p&gt;En este Post crearemos una pequeña y sencilla Azure Function desde el portal web de Azure, esta función recibirá algunos parámetros para procesarlos y devolver un resultado esto hará el trabajo de un API, luego crearemos una aplicación móvil multiplataforma con Xamarin Forms para consumirla.&lt;/p&gt;

&lt;p&gt;Problema a resolver con este proyecto: &lt;strong&gt;Calcular tu peso ideal&lt;/strong&gt;&lt;br&gt;
Para calcular el peso ideal hay que saber manejar el Índice de Masa Corporal (IMC), una medida que nos ayuda a detectar si nos encontramos dentro de los valores saludables o no.&lt;br&gt;
La Organización Mundial de la Salud estima que un peso saludable es el que se sitúa entre valores de 18,5 y 24,9.&lt;br&gt;
Los valores inferiores a 18,5 nos indican un peso demasiado bajo.&lt;br&gt;
Si son iguales o superiores a 25 se consideraría ya sobrepeso. Si supera los 30 se trata de obesidad.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fft1eopeq5fdltg8rwowv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fft1eopeq5fdltg8rwowv.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El peso ideal se calcula dividiendo el peso en kilogramos por el cuadrado de la altura en metros (kg/m2). Ejemplo: Si una persona pesa 60 kilos y mide 1,50 el resultado final sería 26, 6. Según Aragón, en este ejemplo la persona tendría ligero sobrepeso.&lt;br&gt;
Hay que tener en cuenta que el cálculo del IMC “sólo es válido entre personas de 20 y 65 años y nunca para niños, embarazadas, madres lactantes o personas que realizan mucho deporte o de alta competición”.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Definición de tareas Azure Function y Aplicación móvil&lt;/strong&gt;&lt;br&gt;
 Crearemos una aplicación móvil que calculará el peso ideal de una persona, esta recibirá los datos que necesitamos (peso y altura de una persona). Nuestra función de azure hará el procesamiento por medio de una petición HTTP Post, recibirá los datos serializados como un objeto JSON, realizará la operación para obtener el resultado final IMC para finalmente mostrar ese resultado en nuestra aplicación móvil.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Creando una función de Azure
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;En primera instancia necesitas una suscripción de Azure, puedes obtener una aquí &lt;a href="https://azure.microsoft.com/es-es/free/" rel="noopener noreferrer"&gt;https://azure.microsoft.com/es-es/free/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Después necesitamos crear el recurso, puedes buscarlo en la barra de búsqueda o en la sección de nuevo recurso, selecciona Azure Function.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzjeoax2zhdkynsaa7z0c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzjeoax2zhdkynsaa7z0c.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Necesitamos completar la información obligatoria para crear nuestra Azure Function.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkjllcb5qjsfpm6bst8xr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkjllcb5qjsfpm6bst8xr.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F33o5h1jv64v9nk1c0hwp.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F33o5h1jv64v9nk1c0hwp.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Una vez completados los datos Azure nos mostrará la información con las características de nuestra Azure Function, pulsamos en crear y esperamos a que se cree el recurso, Azure nos notificará cuando todo este listo.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjcgfnym7sumpb23n0kb1.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fjcgfnym7sumpb23n0kb1.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Una vez creado el recurso necesitamos seguir unos pasos más.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxe8s488gbhjkij8l2ize.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fxe8s488gbhjkij8l2ize.png" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Debemos elegir un entorno de desarrollo, en este caso seleccionamos en el Portal.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3ftzxgwnjlikfhrvwie7.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F3ftzxgwnjlikfhrvwie7.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Seleccionamos WebHook y API.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmlkk9mvkqp59jab3h2ud.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmlkk9mvkqp59jab3h2ud.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Al crear una Azure Function esta se crea con código por defecto, eleminaremos ese código y lo sustituiremos por el siguiente y pulsaremos en el botón Guardar y Ejecutar.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6r2b1n9g6rbpbltqwsdj.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F6r2b1n9g6rbpbltqwsdj.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Puedes encontrar el código para la función de Azure en el repositorio de github. Link al final de post.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Tenemos lista nuestra Azure Function!&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Previo a consumirla desde Xamarin Forms haremos una prueba desde un cliente HTTP en este caso PostMan, necesitamos obtener la url para poder realizar la petición HTTP, da click en la opción &lt;em&gt;Obtener la dirección URL de la función&lt;/em&gt;.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fexvrwojrt9ittoea3w8f.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fexvrwojrt9ittoea3w8f.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Ahora vamos a PostMan y utilizamos la Url obtenida en el paso anterior, debemos utilizar el verbo HTTP Post y enviar el objeto JSON en el cuerpo de la petición.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyyqkaki75a5boo213atx.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyyqkaki75a5boo213atx.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;El resultado también es un objeto JSON que contiene una propiedad llamada result, el valor que tiene asignado result es lo que esperamos como respuesta. &lt;/p&gt;

&lt;h2&gt;
  
  
  Creando App Móvil Xamarin Forms
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Para este proyecto utilizaré Visual Studio 2019 Preview, y crearé un proyecto Xamarin Forms 4.3.&lt;/li&gt;
&lt;li&gt;Me apoyaré del patrón de arquitectura de Software MVVM para tratar de desacoplar lo máximo posible la interfaz de usuario de la lógica de la aplicación, buscando factorizar el código de la aplicación en las clases correctas y en establecer la interacción de clases entre sí.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inicialmente estructuraremos los directorios de la Aplicación de la siguiente manera:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyjl8fd3yvxardpl9fkm4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fyjl8fd3yvxardpl9fkm4.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; la página que se crea por defecto MainPage.xaml fue movida al directorio Views, no olvidar cambiar el namespace en el archivo MainPage.xaml.cs y modificar la referencia en el archivo xaml.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Seguidamente abrimos el administrador de paquetes nugets para la solución y vamos instalar el nuget Newtonsoft.Json en el proyecto NET-Standard.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F75qq3rdy0wgqjzxy2mdw.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F75qq3rdy0wgqjzxy2mdw.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora vamos a crear 3 clases en el directorio Models, las clases modelo se llamaran Response, PesoIdealParam y PesoIdealResult.&lt;/p&gt;

&lt;p&gt;Response.cs este modelo hace referencia al resultado que obtenemos al realizar una petición HTTP hacia nuestra Azure Function corriendo en Azure, consta de 4 propiedades: IsSucces toma un valor booleano que depende del éxito o excepción al realizar la petición HTTP, Message almacena el mensaje de respuesta al realizar la petición HTTP, StatusCode como toda petición HTTP retorna un StatusCode este se almacena en esta propiedad y por último DataResult un tipo Object que es capaz de almacenar cualquier tipo de objeto o lista de objetos que pueda retornar la petición HTTP.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc5avddf8jtkymp8bxj2r.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc5avddf8jtkymp8bxj2r.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PesoIdealParam.cs este modelo lo utilizaremos para enviar los valores recibidos en está app, vamos a serializarlos en formato JSON para luego enviarlos a nuestra Azure Function y se encargue de procesarlos, en este punto tendremos 3 propiedades que necesitaremos enviar: el nombre de la persona, el peso en kilogramos y la altura en metros, las propiedades de clase en C# las manejaremos con mayúsculas aunque en nuestra Azure Function están con minúscula, por eso es necesario utilizar las Anotaciones de Datos [Data Annotations] como decorador de cada propiedad de clase, los Data Annotations poseen el nombre de la propiedad como se gestiona en el backend y el nombre en mayúscula en la propiedad de clase es como gestionamos esa propiedad dentro de la app.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnoquy2rclwig9y2ctrso.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnoquy2rclwig9y2ctrso.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;PesoIdealResult.cs este modelo únicamente posee una propiedad que se encargará de almacenar el resultado recibido del proceso que realiza nuestra Azure Function.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flf263b1d9jbyaug8jqaq.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Flf263b1d9jbyaug8jqaq.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora crearemos una clase llamada AzureFunctionService.cs en el directorio de Services, aquí encapsularemos la lógica para realizar la petición HTTP hacia nuestra Azure Function mediante un método asíncrono de retorna un Task de Response.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmv3b1w2plr6285fls49o.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmv3b1w2plr6285fls49o.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn1481kbmcdkku0oj4329.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fn1481kbmcdkku0oj4329.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El siguiente paso es crear la clase ViewModel llamada MainViewModel.cs en el directorio ViewModels, este archivo encapsula la lógica de la aplicación encargada de utilizar diferentes clases que contienen diferentes responsabilidades.&lt;br&gt;
MainViewModel.cs contiene las propiedades, atributos, validaciones, uso del servicio para utilizar Azure Function dentro de un método que responde al evento de ejecución dentro de un command de Xamarin Forms. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgzg9l9ipxakidbcqn2bl.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgzg9l9ipxakidbcqn2bl.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkjrcb51r2d0dmegukweg.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fkjrcb51r2d0dmegukweg.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsy2wenatly1uouk6qap4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fsy2wenatly1uouk6qap4.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdd5omt6jz6n5lzs58iga.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdd5omt6jz6n5lzs58iga.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7v92ggonzqur7k4dqndq.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F7v92ggonzqur7k4dqndq.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0n1wuszftc72ay596ec4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0n1wuszftc72ay596ec4.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;MainViewModel.cs hereda de BaseViewModel.cs una clase que contiene una implementación de INotifyPropertyChanged con el evento que notificará los cambios de cada propiedad en la ViewModel.  &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;En este paso modificaremos la vista MainPage.xaml e inicialmente es necesario agregar la referencia al namespace al que pertenece la clase MainViewModel.cs y seguidamente establecemos el Binding Context para esta página, después creamos los controles necesarios para cada propiedad (Entry, Label, Button, Activity Indicator, etc) y establecemos el Binding correspondiente hacía cada una de las propiedades definidas en la clase ViewModel.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm79j17eo7yvjr3tqiaef.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm79j17eo7yvjr3tqiaef.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0x1qb1g5dgmkhta3bktf.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0x1qb1g5dgmkhta3bktf.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fipeq362fbqv3k4uv54sy.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fipeq362fbqv3k4uv54sy.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ya tenemos todo el código necesario para ejecutar nuestra app, visualmente se ve de la siguiente manera:&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzk7i7g0l48kjl5i3hgp3.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fzk7i7g0l48kjl5i3hgp3.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora ingresaremos los datos para que nuestra Azure Function pueda procesarlos y devolvernos un resultado, controlando todo desde nuestra app.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm3oli0ya9no1p1n40atd.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fm3oli0ya9no1p1n40atd.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz9zu9we5eym6isd3lzm1.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz9zu9we5eym6isd3lzm1.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Como podemos observar nuestra aplicación funciona correctamente y podemos verificar los diferentes resultados que podemos obtener con base a la información enviada a nuestra Azure Function.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Conclusión&lt;/strong&gt;&lt;br&gt;
Tradicionalmente, las aplicaciones móviles estaban conectadas a servicios locales. La creación del nivel de servicio requería el conocimiento de la plataforma de servidor y un paradigma de programación. Los desarrolladores trabajaban en configurar los servidores de forma adecuada. A veces se dedicaban días o incluso semanas a la creación de una canalización de implementación confiable y segura, aunque esto se sigue haciendo.&lt;br&gt;
Ahora sabemos que con Azure Functions podemos crear lógica de negocios sin necesidad de convertirnos en expertos en lo relacionado con el servidor, podemos crear un backend en cuestión de minutos y agilizar el desarrollo de nuestras apps móviles.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Link al Repositorio en GitHub&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://github.com/EbarriosCode/Xamarin-Azure-Functions" rel="noopener noreferrer"&gt;https://github.com/EbarriosCode/Xamarin-Azure-Functions&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Referencias&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/azure/azure-functions/&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/xamarin/xamarin-forms/data-cloud/azure-services/azure-functions?tabs=windows" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/xamarin/xamarin-forms/data-cloud/azure-services/azure-functions?tabs=windows&lt;/a&gt;&lt;br&gt;
&lt;a href="https://cuidateplus.marca.com/alimentacion/diccionario/indice-masa-corporal-imc.html" rel="noopener noreferrer"&gt;https://cuidateplus.marca.com/alimentacion/diccionario/indice-masa-corporal-imc.html&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.efesalud.com/aprende-calcular-peso-saludable/" rel="noopener noreferrer"&gt;https://www.efesalud.com/aprende-calcular-peso-saludable/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>csharp</category>
      <category>mobile</category>
      <category>dotnet</category>
    </item>
    <item>
      <title>Xamarin Forms y Entity Framework Core SQLite, Persistencia y Acceso a Datos Locales en dispositivos móviles</title>
      <dc:creator>Eduardo Barrios</dc:creator>
      <pubDate>Tue, 17 Dec 2019 07:02:20 +0000</pubDate>
      <link>https://forem.com/ebarrioscode/xamarin-forms-y-entity-framework-core-sqlite-persistencia-y-acceso-a-datos-locales-en-dispositivos-moviles-4al6</link>
      <guid>https://forem.com/ebarrioscode/xamarin-forms-y-entity-framework-core-sqlite-persistencia-y-acceso-a-datos-locales-en-dispositivos-moviles-4al6</guid>
      <description>&lt;p&gt;Esta publicación forma parte del segundo calendario #AdvientoXamarin en español, una iniciativa liderada por Luis Beltrán.&lt;/p&gt;

&lt;p&gt;A continuación les traigo un aporte sencillo pero no menos importante en el desarrollo de aplicaciones con Xamarin Forms, estoy seguro que en más de una ocasión hemos necesitado guardar información en una base de datos local dentro del dispositivo móvil y regularmente con el motor de Base de Datos SQLite tal cuál es el caso en esta implementación. A la hora de trabajar con datos para los desarrolladores .NET una opción muy familiar es Entity Framework debido a que puedes utilizarlo en diversas soluciones .NET tales como Proyectos de Consola, Windows Form, ASP.NET Web Forms, ASP.NET MVC, WebApis, WPF, UWP, etc. Obviamente a la lista anterior debes incluir aplicaciones móviles multiplataforma con Xamarin Forms.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;EF Core&lt;/strong&gt;&lt;br&gt;
Entity Framework es un ORM (object-relational mapper) que permite a los desarrolladores trabajar con bases de datos utilizando objetos .NET.&lt;/p&gt;

&lt;p&gt;Microsoft define Entity Framework (EF) Core como una versión ligera, extensible, de código abierto y multiplataforma de la popular tecnología de acceso a datos Entity Framework, EF Core soporta numerosos tipos de bases de datos tales como: SQLite, SqlServer, MySQL, Oracle, PostgreSQL, Firebird, etc. &lt;br&gt;
En este post demostraremos lo fácil que es utilizar EF Core en aplicaciones de Xamarin Forms para acceder a una base de datos local SQLite en las plataformas Android y iOS.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; Aunque esta implementación utiliza el patrón de arquitectura de software MVVM, la idea principal es demostrar el fácil acceso a datos y todo el provecho que le puedes sacar a EF Core, más aún si haz tenido experiencia con EF Core en otro tipo de soluciones .NET&lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;Esta es una simple implementación que trata de como almacenar registros en una Base de Datos SQLite, utilizaré los modelos Albumes y Artistas que he utilizado en post anteriores, crearemos una vista que contenga un formulario para crear albumes y posteriormente una vista que contenga un elemento de lista para mostrar los albumes almacenados en la Base de Datos.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Empezaremos creando un nuevo proyecto de Xamarin Forms en Visual Studio 2019.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--laEc4GQ_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/v9r7nbvo7m7fcucrv24w.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--laEc4GQ_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/v9r7nbvo7m7fcucrv24w.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Teniendo nuestro proyecto creado la primero será agregar el paquete Nuget Microsoft.EntityFrameworkCore.Sqlite en el proyecto compartido de Xamarin Forms.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--v5P4f0Nb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qzqn25p3r9tbhegiveq2.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--v5P4f0Nb--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qzqn25p3r9tbhegiveq2.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora vamos a estructurar el código del proyecto compartido creando los siguientes directorios:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3nR33FLN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/0wy87euafwypalftoer7.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3nR33FLN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/0wy87euafwypalftoer7.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Nota:&lt;/strong&gt; La página MainPage.xaml que se crea por defecto al crear el proyecto fue movida al directorio Views, el namespace también fué modificado de XamEFCore que hace referencia a la raíz en el proyecto compartido a XamEFCore.Views y de la misma manera en el codebehind MainPage.xaml.cs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;El siguiente paso es crear un clase que sirva como contexto de datos, si ya haz trabajado con otras soluciones .NET como MVC, WebApis, etc, seguramente esto te será muy familiar. &lt;br&gt;
El contexto de datos es una clase en una solución .NET que hereda de la clase DbContext contenida en el namespace System.Data.Entity.DbContext y nos permite realizar las siguientes tareas:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Administrar la conexión de la base de datos&lt;/li&gt;
&lt;li&gt;Configurar modelos y relación&lt;/li&gt;
&lt;li&gt;Consultar base de datos&lt;/li&gt;
&lt;li&gt;Guardar datos en la base de datos&lt;/li&gt;
&lt;li&gt;Configurar el seguimiento de cambios&lt;/li&gt;
&lt;li&gt;Almacenamiento en caché&lt;/li&gt;
&lt;li&gt;Gestión de transacciones&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Crearemos la clase contexto la llamaré AppDbContext y heredará de la clase DbContext, no olvidar agregar la referencia a Microsfot.EntityFrameworkCore.&lt;br&gt;
Crearemos un atributo propio de la clase AppDbContext que nos servirá para setear la ruta y el nombre de la base datos para cada plataforma en este caso Android y iOS, este valor lo recibiremos mediante el método constructor de este contexto, seguidamente exponemos las propiedades DbSet que representan colecciones de las entidades especificadas en el contexto y sobreescribimos el método OnConfiguring para indicarle a EF Core que utilizaremos SQLite mediante el optionsBuilder pasandole como parámetro la ruta y el nombre de la base de datos que ya recuperamos y asignamos al atributo DbPath. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: La ruta debe obtenerse en tiempo de ejecución.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--I_tvC9eu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/cybtse01qgzy84d8n34v.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--I_tvC9eu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/cybtse01qgzy84d8n34v.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En el siguiente paso vamos a recuperar la ruta en donde se almacenará la base datos específicamente para cada plataforma, debemos tomar en cuenta que el manejo de archivos y directorios es independiente para cada plataforma por lo que el almacenamiento de la base de datos se maneja de diferente manera tanto en Android como en iOS. Utilizaremos el Servicio de Dependencias (Dependency Service) de Xamarin Forms que nos permitirá implementar funcionalidades nativas para cada plataforma en este caso recuperar la ruta de almacenamiento de la base de datos, a grandes rasgos, Dependency Service consiste en crear una interface en el proyecto compartido e implementar esa interface en cada proyecto nativo con funcionalidades nativas para lograr comportamientos o funcionalidades propias de cada sistema operativo. &lt;br&gt;
Sabiendo lo anterior procedemos y en el proyecto compartido de Xamarin Forms crearemos una interface en el directorio Interfaces y la llamaremos IConfigDataBase la cuál únicamente contendrá un método que retorna un string que hace referencia a la ruta de almacenamiento de la base de datos y recibe un parámetro tipo string que hace referencia al nombre de la base de datos, cada implementación de esta interface se encargará de encadenar o combinar la ruta y el nombre para devolver un único string.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--skIyVXJS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/7j37x20koev7hla4f0om.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--skIyVXJS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/7j37x20koev7hla4f0om.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora vamos a implementar la interface anterior en el proyecto de Xamarin.Android, crearemos un directorio llamado Implementations que contendrá una clase llamada ConfigDataBase e implementamos el método GetFullPath especifícamente para Android.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--whsLOgyL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yjsjkikd6fvel6km9swo.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--whsLOgyL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yjsjkikd6fvel6km9swo.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Realizaremos nuevamente el paso anterior pero esta vez para el proyecto Xamarin.iOS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QwNzVh3w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/nnecsjnulg016qsr1edz.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QwNzVh3w--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/nnecsjnulg016qsr1edz.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En el siguiente paso vamos a obtener una instancia del contexto de datos cuando se inicia la aplicación, esto garantiza que cuando ésta se ejecute por primera vez, independientemente de la plataforma en la que corra en tiempo de ejecución obtendremos la ruta de almacenamiento de la base de datos y se la mandaremos al método constructor del contexto de datos, para ello iremos al codebehind de App.xaml, escribiremos un método Static que regresará una nueva instancia del contexto, utilizamos el Dependency Service para obtener la ruta de almacenamiento de cada plataforma, seguidamente utilizaremos ese método Static en el método constructor y crearemos la base de datos con la instrucción Database.EnsureCreated().&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--unqX6hGd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4s5lom6ysaq2cnt6xb92.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--unqX6hGd--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/4s5lom6ysaq2cnt6xb92.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Crearemos una clase que nos sirva como Servicio para acceder y realizar operaciones a la base de datos mediante EF Core y Linq, en este ejemplo nos centraremos en Crear y Listar objetos tipo Album, la clase se llamará DBDataAccess y estará dentro del directorio Services.&lt;br&gt;
Obtenemos el contexto creado en el inicio de la aplicación y lo utilizamos para el manejo de objetos.&lt;/p&gt;

&lt;p&gt;El método Create devuelve un bool y su valor depende de, si el objeto se creó correctamente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--KC4D5yBz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e5xp57pp2v178gb3r2kh.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--KC4D5yBz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/e5xp57pp2v178gb3r2kh.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El método Get es un método genérico que devuelve una lista de objetos y recibe 3 parámetros: parámetro 1 una condición, parámetro 2 ordenar por algún atributo propio del modelo y parámetro 3 la relación con otro modelo en este caso Artista.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--aXf-2r6P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hk0dq56us40cbxyh8ete.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--aXf-2r6P--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/hk0dq56us40cbxyh8ete.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Realicé unas modificaciones para crear un ListView con dos opciones de menú crear y listar registros y se ve de la siguiente manera:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Rdr06WHJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/8wbtb5rtx2azuctorshf.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Rdr06WHJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/8wbtb5rtx2azuctorshf.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: No entraré en detalles en cuanto al código de la Vista y el ViewModel asociado a la vista principal, puedes revisar el código en el repositorio de github.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ahora crearemos en el directorio Views una Vista llamada AlbumPage aquí agregaremos un formulario para ingresar datos de Albumes y que estos se almacenen en la base de datos, previamente crearemos una clase llamada AlbumesViewModel en el directorio ViewModels, esto para poder agregar el BindingContext mediante código XAML en la vista.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--iy4OKK2M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ci44inom8qgbyjwref22.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--iy4OKK2M--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ci44inom8qgbyjwref22.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--sJ_xy9b6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/q0xoul8ggrkvbey7zugm.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--sJ_xy9b6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/q0xoul8ggrkvbey7zugm.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la clase AlbumesViewModel crearemos la propiedades a enlazar mediante Binding con la Vista.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--b-d8DidV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/a41wa1ov946j7748bl2u.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--b-d8DidV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/a41wa1ov946j7748bl2u.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--UPefP9PT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ebdzy267sgm2q9fkl79m.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--UPefP9PT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ebdzy267sgm2q9fkl79m.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Crearemos el Command que se ejecutará cuando presionemos el Button Guardar, y utilizaremos el DataService de Albumes e invocamos al método Create y le pasamos el nuevo objeto Album que construimos a partir de los datos ingresados en el formulario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--max7F40O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/01tkyi17w3x23x9lu720.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--max7F40O--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/01tkyi17w3x23x9lu720.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nuestra View para crear Albumes se verá de la siguiente manera:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lOX2ZXsr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/xqn68vx7lszbj6xw8gdc.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lOX2ZXsr--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/xqn68vx7lszbj6xw8gdc.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Llenamos el formulario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--2T4jpDue--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dn4r3k5y2rxev37h9vxe.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--2T4jpDue--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/dn4r3k5y2rxev37h9vxe.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: El Picker de Artistas se carga mediante una lista de Artistas almacenada en la base de datos, utilicé un método temporal para crear dichos artistas en la tabla Artista, lo utilice únicamente para tener datos en dicha tabla, en otro escenario real esa lista podría venir de un WebApi o cualquier otra fuente de datos, no haré énfasis en esa funcionalidad, puedes revisar el código en el repositorio de github.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_YSVBtEi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rmiynubje8qctw3qkjo4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_YSVBtEi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/rmiynubje8qctw3qkjo4.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al presionar el Button Guardar se ejecuta el Command y el resultado es el siguiente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--Cjc_NJEz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/2ettyr8yom105uuw77um.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--Cjc_NJEz--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/2ettyr8yom105uuw77um.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ya es posible almacenar Albumes, el siguiente paso es mostrar un ListView con la lista de Albumes recuperada de la base de datos.&lt;/p&gt;

&lt;p&gt;Crearemos una nueva View en el directorio Views y la llamaremos AlbumesPage.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_sZE4vhU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/lbke8xvz544jl9mracqj.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_sZE4vhU--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/lbke8xvz544jl9mracqj.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PjSdRlVf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/25gojoipcoqlii52f98k.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PjSdRlVf--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/25gojoipcoqlii52f98k.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--rFYXePEJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yiwyvyp5i3p2q4h02esa.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--rFYXePEJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/yiwyvyp5i3p2q4h02esa.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Nota: Esta View utiliza el mismo ViewModel en su propiedad BindingContext.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ahora crearemos un método para recuperar esa lista de Albumes almacenada en la tabla Albumes de la base de datos y lo invocaremos en el método constructor de AlbumesViewModel.&lt;/p&gt;

&lt;p&gt;El resultado es el siguiente:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--ebNDPBZQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/kd06gl6lycge69z84hn7.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--ebNDPBZQ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/kd06gl6lycge69z84hn7.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Guardamos más Albumes en la base de datos y podremos visualizar como el ListView crece.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--audsFvG4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/sxw5wprrx2ytjcvvnxto.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--audsFvG4--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/sxw5wprrx2ytjcvvnxto.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusión
&lt;/h2&gt;

&lt;p&gt;Personalmente como desarrollador .NET encuentro muchas ventajas sobre el uso de Entity Framework Core para manipular datos y bases de datos, el rendimiento de EF Core ha mejorado exponencialmente con respecto a versiones anteriores, además manipular los datos como objetos y realizar consultas mediante Linq es genial y más si previo a utilizarlo con Xamarin Forms lo utilizas en otras soluciones .NET &lt;/p&gt;

&lt;p&gt;Link al repositorio en GitHub: &lt;br&gt;
&lt;a href="https://github.com/EbarriosCode/Xamarin-y-Entity-Framework-Core-SQLite"&gt;https://github.com/EbarriosCode/Xamarin-y-Entity-Framework-Core-SQLite&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Referencias: &lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/ef/overview"&gt;https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/ef/overview&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.microsoft.com/es-es/ef/ef6/fundamentals/working-with-dbcontext"&gt;https://docs.microsoft.com/es-es/ef/ef6/fundamentals/working-with-dbcontext&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.entityframeworktutorial.net/efcore/entity-framework-core-dbcontext.aspx"&gt;https://www.entityframeworktutorial.net/efcore/entity-framework-core-dbcontext.aspx&lt;/a&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>xamarin</category>
      <category>mobile</category>
      <category>efcore</category>
    </item>
    <item>
      <title>Patrón Repositorio (Repository Pattern) y Unidad de Trabajo (Unit Of Work) en ASP.NET Core WebApi 3.0</title>
      <dc:creator>Eduardo Barrios</dc:creator>
      <pubDate>Sat, 07 Dec 2019 18:19:56 +0000</pubDate>
      <link>https://forem.com/ebarrioscode/patron-repositorio-repository-pattern-y-unidad-de-trabajo-unit-of-work-en-asp-net-core-webapi-3-0-5goj</link>
      <guid>https://forem.com/ebarrioscode/patron-repositorio-repository-pattern-y-unidad-de-trabajo-unit-of-work-en-asp-net-core-webapi-3-0-5goj</guid>
      <description>&lt;p&gt;Una aplicación de software típica naturalmente necesitará acceder a algún tipo de almacén de datos para llevar a cabo operaciones CRUD (Crear, Leer, Actualizar, Eliminar) en los datos, por lo general esto podría ser algún tipo de base de datos, sistema de archivos o cualquier tipo de mecanismo de almacenamiento utilizado para persistir de información.&lt;br&gt;
En algunos casos guardar o crear datos puede requerir persistencia en archivos nuevos o crear una nueva fila en una tabla de una base de datos, en otros casos guardar datos nuevos puede requerir varias interacciones con varios servicios basados ​​en la web o aplicaciones y otros servicios que no son generalmente gestionados por nosotros mismos.&lt;/p&gt;

&lt;p&gt;Para ambos casos podemos hacer uso del patrón repositorio (Repository Pattern) y una unidad de trabajo (Unit Of Work), pero, ¿qué es el patrón repositorio? &lt;br&gt;
El patrón repositorio consiste en separar la lógica que recupera los datos y los asigna a un modelo de entidad de la lógica de negocios que actúa sobre el modelo, esto permite que la lógica de negocios sea independiente del tipo de dato que comprende la capa de origen de datos, en pocas palabras un repositorio media entre el dominio y las capas de mapeo de datos, actuando como una colección de objetos de dominio en memoria (M. Fowler), ahora bien, ¿qué es el patrón unidad de trabajo? &lt;br&gt;
Este centraliza las conexiones a la base de datos realizando un seguimiento de todo lo que sucede durante una transacción cuando se usan capas de datos y revertirá la transacción si Commit() no se ha invocado o existen incongruencias lógicas.&lt;/p&gt;

&lt;p&gt;Para este ejemplo utilizaremos un repositorio genérico y una unidad de trabajo aplicándolo al proyecto de Albumes y Artistas que contiene una base de datos en memoria de sql server. Este proyecto lo he utilizado en post anteriores, he realizado algunas adaptaciones al código del repositorio que me parecen geniales agregando programación asíncrona, separando servicios, desacoplando componentes para lograr una mejor infraestructura dentro del proyecto y que puedan utilizarla en sus proyectos.&lt;/p&gt;

&lt;p&gt;Vamos a crear un proyecto con una solución en blanco en Visual Studio 2019 Preview, luego crearemos 3 carpetas de soluciones y dentro cada carpeta agregaremos un proyecto que hace referencia a las capas WebApi que contendrá el manejo de Controllers para exponer o almacenar datos, Entities que hace refencia a los modelos, en un escenario mas sencillo los modelos los crearíamos en el proyecto WebApi pero recuerda que buscamos desacoplar componentes, la tercer capa llamada DataAccess que se encargará de acceder a la información de la base de datos mediante un repositorio genérico y afectar la base de datos mediante una unidad de trabajo. Los proyectos Entities y DataAccess son bibliotecas de clases .NET Standard. La organización del proyecto quedaría de la siguiente manera:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkaz7t60m7p45of2mcu3z.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkaz7t60m7p45of2mcu3z.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En el proyecto DataAccess crearemos las Clases que implementan las Interfaces del repositorio genérico y la unidad de trabajo, seguidamente haremos uso de inyección de dependencias de ambos, si no sabes que es inyección de dependencias revisa mi post anterior acerca de &lt;a href="https://dev.to/ebarrioscode/inyeccion-de-dependencias-di-en-asp-net-core-mejores-practicas-para-escribir-codigo-reutilizable-escalable-y-desacoplado-kho"&gt;Inyección de dependencias en. NET Core.&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Creamos la unidad de trabajo, su respectiva Interface y Clase.&lt;br&gt;
UnitOfWork utiliza el contexto de datos que pertenece a la capa de Entities, no olvidar hacer referencia a dicho proyecto. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5t0jszoww2oihwar6d4k.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5t0jszoww2oihwar6d4k.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Luego crearemos el repositorio genérico.&lt;br&gt;
Puedes notar que tradicionalmente se inyecta una propiedad de contexto de datos en el constructor del repositorio pero para esta implementación inyectamos una propiedad de tipo IUnitOfWork, esto para lograr centralizar las operaciones a la base de datos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5l5hwibvke7ln0yvoq0n.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F5l5hwibvke7ln0yvoq0n.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F8aprk9cs7mumf8a8nsk3.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F8aprk9cs7mumf8a8nsk3.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ffuruens2h3kt9wmu3dtx.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Ffuruens2h3kt9wmu3dtx.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7abf9h2jvwfood51o03s.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F7abf9h2jvwfood51o03s.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Nos centraremos en las opciones leer y crear, sobrecargamos el método GetAsync para poder agregar una condición, ordenar por algún atributo propio del modelo y agregar relaciones con otros modelos mediante alguna propiedad de navegación.&lt;/p&gt;

&lt;p&gt;Ahora vamos a agregar la dependencia en el contenedor de control de inversión IoC, está clase se crea en una carpeta llamada Middleware, este nombre es arbitrario y debe estar situada en el proyecto WebApi.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzfncphayv7tjqob91bfg.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fzfncphayv7tjqob91bfg.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seguidamente utilizamos el contenedor de inversión de control para inyectar el servicio en la clase Startup método ConfigureServices en el proyecto WebApi.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fyoaqga88v6d0flqbfe12.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fyoaqga88v6d0flqbfe12.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora vamos a utilizar el repositorio genérico y la unidad de trabajo en nuestro Controller, debemos inyectar la interface IGenericRepository pero debemos darle un tipo y en este caso debe ser tipo Album, inyectamos la interface de unidad de trabajo IUnitOfWork, después asignamos la inicialización que el IoC se encargo de instanciar en el inicio y seguidamente podemos proceder a utilizar alguno de los métodos del repositorio, en este caso el método GetAsync del repositorio en el método Api Get, nótese que estamos pasando 3 parámetros: parámetro 1 una condición, parámetro 2 ordenar por algún atributo propio del modelo y parámetro 3 la relación con otro modelo en este caso Artista. Para el caso del método Api Create utilizamos el método del repositorio CreateAsync el cuál recibe un modelo serializado en formato json a través del verbo HTTP Post.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fb9j5omndnv3b62489bmg.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fb9j5omndnv3b62489bmg.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finalmente vamos a probar el funcionamiento de este proyecto, nos apoyaremos de PostMan para realizar las peticiones HTTP hacía nuestros métodos Api.&lt;/p&gt;

&lt;p&gt;Tras compilar, ejecutar y hacer una llamada HTTP Get al método api Get del WebApi obtenemos el listado de Albumes relacionados con el modelo Artista.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh1gzhd4yai0wv15q025g.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fh1gzhd4yai0wv15q025g.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Comprobamos el funcionamiento del método api Create enviando un objeto json con la propiedades de Album y no olvidar cambiar el tipo de petición a HTTP Post en PostMan.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fiu2xo6c7t6rnhf6xvvy7.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fiu2xo6c7t6rnhf6xvvy7.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El nuevo objeto se creó correctamente, ahora volveremos a realizar la petición al método Get para comprobar la existencia del nuevo registro en la lista de Albumes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F91fmpnuhu4hxl6eo0bel.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F91fmpnuhu4hxl6eo0bel.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como podemos observar está implementación funciona correctamente, hemos utilizado el patrón repositorio y una unidad de trabajo. &lt;br&gt;
Entre los beneficios de utilizar el patrón repositorio podemos mencionar centralización de la lógica de acceso a datos, punto de sustitución para las pruebas unitarias y arquitectura flexible que se puede adaptar a medida que evoluciona el diseño general de la aplicación. &lt;br&gt;
En cuanto al patrón unidad de trabajo personalmente uso la unidad de trabajo para reducir mucha inyección de dependencia, puedo tener una unidad de trabajo de la base de datos y una vez que use la inyección de dependencias para inyectar el contexto de la Base de datos en esa unidad de trabajo, no necesito inyectar cada repositorio de modelos donde quiero usarlos, pero solo accederé a los repositorios desde el unidad de trabajo, esto también me ayuda a crear instancias de un repositorio solo cuando lo necesito en un método específico.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusión&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;El patrón repositorio está destinado a crear una capa de abstracción entre la capa de acceso a datos y la capa empresarial para que pueda ayudar a aislar la aplicación de los cambios en el almacén de datos y facilitar las pruebas unitarias automatizadas para el desarrollo basado en pruebas.&lt;/p&gt;

&lt;p&gt;En esta implementación hacemos uso de Entity Framework Core en una implementación de la Unidad de Trabajo y Patrón Repositorio. &lt;br&gt;
Por lo tanto, no es del todo necesario en estos días envolver Entity Framework Core en un patrón de Unidad de Trabajo, porque básicamente se está envolviendo una abstracción sobre una abstracción, pero para fines de entender como funciona Unidad de trabajo hacemos uso de Entity Framework Core.&lt;br&gt;
Además únicamente tenemos un repositorio y el objetivo de la unidad de trabajo es centralizar y unificar repositorios.&lt;/p&gt;

&lt;p&gt;Link al repositorio en Github:&lt;br&gt;
&lt;a href="https://github.com/EbarriosCode/RepositoryUnitOfWorkNetCore3" rel="noopener noreferrer"&gt;https://github.com/EbarriosCode/RepositoryUnitOfWorkNetCore3&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Referencias:&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-design&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-implemenation-entity-framework-core" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/dotnet/architecture/microservices/microservice-ddd-cqrs-patterns/infrastructure-persistence-layer-implemenation-entity-framework-core&lt;/a&gt;&lt;br&gt;
&lt;a href="https://martinfowler.com/eaaCatalog/repository.html" rel="noopener noreferrer"&gt;https://martinfowler.com/eaaCatalog/repository.html&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.martinfowler.com/eaaCatalog/unitOfWork.html" rel="noopener noreferrer"&gt;https://www.martinfowler.com/eaaCatalog/unitOfWork.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Inyección de Dependencias(DI) en ASP.NET Core, mejores prácticas para escribir código reutilizable, escalable y desacoplado</title>
      <dc:creator>Eduardo Barrios</dc:creator>
      <pubDate>Sat, 16 Nov 2019 04:24:07 +0000</pubDate>
      <link>https://forem.com/ebarrioscode/inyeccion-de-dependencias-di-en-asp-net-core-mejores-practicas-para-escribir-codigo-reutilizable-escalable-y-desacoplado-kho</link>
      <guid>https://forem.com/ebarrioscode/inyeccion-de-dependencias-di-en-asp-net-core-mejores-practicas-para-escribir-codigo-reutilizable-escalable-y-desacoplado-kho</guid>
      <description>&lt;p&gt;Los Desarrolladores de Software siempre estamos en busca de una forma reutilizable para resolver un problema común y para lograrlo es necesario recurrir a estándares como lo son los patrones de diseño de Software. Antonio Leiva define un patrón de diseño como una forma de solucionar un problema que se puede extraer, explicar y reutilizar en múltiples ámbitos.&lt;/p&gt;

&lt;p&gt;Ahora sabemos que es un patrón de diseño, pero!!!&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1q38zdztb1nbtdypokug.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1q38zdztb1nbtdypokug.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Inyección de Dependencias es un patrón de diseño de software que nos permite desarrollar componentes acoplados libremente o desacoplados para obtener como resultado la fácil gestión de cambios a futuro, implementación fácil de pruebas unitarias, factoría para emitir instancias de clases, prevención de fugas de memoria, entre otros.&lt;br&gt;
DI proporciona un mecanismo para la construcción de gráficos de dependencia independientes de las definiciones de clase, aplicando esta técnica nuestras clases van a depender de interfaces y no de implementaciones, esto se relaciona directamente con el primero de los 5 principios para desarrollar software de calidad, haciendo referencia a SOLID y el principio de responsabilidad única.&lt;/p&gt;

&lt;p&gt;Por su parte ASP.NET Core nos permite la utilización del patrón de diseño Inyección de Dependencias sin la necesidad de utilizar librerías de terceros para lograrlo, además ASP.NET Core provee un Contenedor de Inversión de Controles(IoC) quien es el encargado de proveer las instancias de los tipos los cuales le decimos en el inicio de la Aplicación(Startup). &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fr4ivqrs2hh3nymuayza5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fr4ivqrs2hh3nymuayza5.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fd70uo02h8ompadnou8rr.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fd70uo02h8ompadnou8rr.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;br&gt;
Para este post utilizaremos un proyecto WebApi de .NET Core 3.0, utilizaré los mismos modelos, base de datos en memoria y estructura del proyecto de mi post anterior. &lt;/p&gt;


&lt;div class="ltag__link"&gt;
  &lt;a href="/ebarrioscode" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F266312%2F64e4f515-0a74-4eb0-8ac4-76678329e64e.jpg" alt="ebarrioscode"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="/ebarrioscode/base-de-datos-en-memoria-con-asp-net-core-3-0-mvc-entity-framework-core-3950" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;Base de Datos en memoria con ASP.NET Core 3.0 MVC + Entity Framework Core&lt;/h2&gt;
      &lt;h3&gt;Eduardo Barrios ・ Nov 7 '19&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
        &lt;span class="ltag__link__tag"&gt;#csharp&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#dotnet&lt;/span&gt;
        &lt;span class="ltag__link__tag"&gt;#database&lt;/span&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


&lt;p&gt;Vamos a Visual Studio Comunity 2019.&lt;br&gt;
Inicialmente visualizamos el archivo HomeController.cs, este código utiliza un servicio para mostrar un listado de Albumes y su relación con Artista, mediante Entity Framework Core. Por el momento no estamos pensando en inyección de dependencias.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fka7nnvzutpshrlbjlh5q.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fka7nnvzutpshrlbjlh5q.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El servicio utiliza el Contexto de Datos para traer el listado de la Base de Datos.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fs2tj0ytsbf08z69ekwb6.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fs2tj0ytsbf08z69ekwb6.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;La clase contexto WebApiDbContext posee una sobreescritura del método OnConfiguring para enviarle la configuración de la base de datos en memoria y el método constructor está sobrecargado.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3yqjbjktivy65eydzokl.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F3yqjbjktivy65eydzokl.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El resultado es el siguiente&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjxs7j2tlxwd43t4dtk3h.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjxs7j2tlxwd43t4dtk3h.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Analizemos el código anterior, como punto principal vemos que funciona, pero nuestro controlador crea y depende directamente de la instancia de la clase AlbumesService, las dependencias de código son problemáticas y deben evitarse, ¿por qué? supongamos que queremos reemplazar la implementación de AlbumesService, debería modificar el controlador también y esto en un proyecto grande representa problemas porque puede que olvide modificar diferentes controladores que utilicen el mismo servicio y el funcionamiento del sistema seria inconsistente. Un problema más en este código podría ser que si AlbumesService tuviera alguna dependencia esta debe ser configurada en el controlador o clase que utilice el servicio de Albumes. Por otra parte esta implementación como se encuentra en este momento dificultaría la realización de pruebas unitarias debido a que sería difícil probar componentes que no están desacoplados y no hay manera de pasarle un servicio fake porque se está utilizando el servicio de forma explicita como una instancia directa.&lt;/p&gt;

&lt;p&gt;Ahora abordemos la problemática y solucionemos mediante Inyección de Depedencias.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fe18zy9ay895o4ozjonq6.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fe18zy9ay895o4ozjonq6.jpg" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pensemos en Inyección de Dependencias, como primer paso debemos utilizar una interface que nos permita abstraer la implementación de dependencias, vamos a relacionarla con el servicio Albumes.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flilc0zdtp7encofh4p2q.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Flilc0zdtp7encofh4p2q.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El siguiente paso es decirle al servicio de Albumes que implemente la interface IAlbumesService.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkl1e9cvhnj271osn0tku.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fkl1e9cvhnj271osn0tku.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora debemos registrar el servicio en el Contenedor de servicios integrados IServiceProvider que nos proporciona ASP.NET Core, los servicios son registrados en el método ConfigureServices de la clase Startup de la aplicación, una vez definido el servicio debemos registrarlo. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1japgkxptchzodehb9pm.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F1japgkxptchzodehb9pm.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Observemos que para este escenario estamos utilizado el método AddTransient para indicar la interface para el servicio y su implementación, esto hace referencia al ciclo de vida de los servicios que viven en el contenedor. Dentro del contenedor que nos proveé ASP.NET Core existen 3 ciclos de vida básicos los cuales podemos utilizar para inicializar las dependencias desde nuestro contenedor.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Transient: Se crean cada vez que se solicitan desde el contenedor de servicios. Esta vida útil funciona mejor para servicios ligeros y sin estado.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scoped: Se crean una vez por solicitud del cliente(conexión). Se utiliza cuando queremos servir la misma instancia dentro del mismo contexto de una petición HTTP, pero diferente entre distintos contextos HTTP.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Singleton: Se crean la primera vez que se solicitan o cuando Startup.ConfigureServices se ejecuta y se especifica una instancia con el registro del servicio. Cada solicitud posterior utiliza la misma instancia.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Para el paso anterior hay otra alternativa por la que podemos optar, personalmente me gusta la siguiente alternativa que nos recomienda Microsoft, consiste en separar todos los servicios en una clase static dentro de un método que recibe como parámetro el IServiceCollection y lo retorna con los servicios ya registrados y unificados para después inyectar todo en el método ConfigureServices, creamos una carpeta llamada Middleware este nombre es arbitrario y dentro una clase llamada IoC que hace referencia al Contenedor de Inversión de Control.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvv94lts17jsvoua5txin.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fvv94lts17jsvoua5txin.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora invocamos el método AddDependency en el método ConfigureServices en la clase Startup.cs&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fd19w0tgzmeefod9h59uw.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fd19w0tgzmeefod9h59uw.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seguidamente vamos al controlador a cambiar esa instancia explicita que teniamos con AlbumesService y la modificaremos pensando en inyectar dependencias, observemos que ahora en lugar de instanciar AlbumesService tenemos una propiedad de lectura que además es una interface IAlbumesService y en ningún momento la inicializamos nosotros, inyectamos la dependencia en el método constructor y quien se encarga de instanciar el servicio es el contenedor, he aquí la razón de agregar las dependencias en el método ConfigureServices de la clase Startup.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F99f722daenohe5o34g1q.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2F99f722daenohe5o34g1q.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora compilamos, ejecutamos y vamos a la ruta de nuestro WebApi desde Postman y podemos observar que este código funciona, el resultado es el mismo cierto, pero en el estado actual en el que se encuentra nuestro código es mejor, debido a que abordamos las problemáticas anteriormente mencionadas.&lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjxs7j2tlxwd43t4dtk3h.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fthepracticaldev.s3.amazonaws.com%2Fi%2Fjxs7j2tlxwd43t4dtk3h.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En conclusión la técnica de Inyección de Dependencias nos ayuda a escribir código reutilizable debido a que el servicio no se instancia en ningún controlador ni en otra clase que lo utiliza podemos reutilizarlo en N cantidad de controladores y clases que necesitemos, ya que la lógica está encapsulada dentro de un servicio, además es escalable y mantenible, podemos modificar la lógica del servicio sin afectar otras partes de nuestro sistema y evitar inconsistencias lógicas, además el código está desacoplado por lo que fácilmente podemos comprobar el correcto funcionamiento de un fragmento de código en específico.&lt;/p&gt;

&lt;p&gt;Link al repositorio en GitHub:&lt;br&gt;
&lt;a href="https://github.com/EbarriosCode/DependencyInjectionDotNetCore3.0" rel="noopener noreferrer"&gt;https://github.com/EbarriosCode/DependencyInjectionDotNetCore3.0&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Referencias:&lt;br&gt;
&lt;a href="https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.0" rel="noopener noreferrer"&gt;https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.0&lt;/a&gt;&lt;br&gt;
&lt;a href="https://devexperto.com/patrones-de-diseno-software/" rel="noopener noreferrer"&gt;https://devexperto.com/patrones-de-diseno-software/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>dotnet</category>
      <category>csharp</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Base de Datos en memoria con ASP.NET Core 3.0 MVC + Entity Framework Core</title>
      <dc:creator>Eduardo Barrios</dc:creator>
      <pubDate>Thu, 07 Nov 2019 16:13:22 +0000</pubDate>
      <link>https://forem.com/ebarrioscode/base-de-datos-en-memoria-con-asp-net-core-3-0-mvc-entity-framework-core-3950</link>
      <guid>https://forem.com/ebarrioscode/base-de-datos-en-memoria-con-asp-net-core-3-0-mvc-entity-framework-core-3950</guid>
      <description>&lt;p&gt;Utilizar una base de datos en memoria es muy útil cuando necesitamos probar componentes utilizando un escenario muy parecido al que nos provee una conexión a una base de datos real, obviamente esto sin el consumo de recursos y la sobrecarga de las operaciones reales a la base de datos, también es útil cuando no se tiene acceso a la base de datos real que posiblemente se encuentre en un servidor al que no tenemos acceso.&lt;/p&gt;

&lt;p&gt;Cabe mencionar que las bases de datos en memoria están diseñadas para ser una base de datos de propósito general únicamente para pruebas, por lo que no deberíamos tratar de imitar a una base de datos relacional ni tratar de llevar este tipo de técnica a un ambiente productivo.&lt;/p&gt;

&lt;p&gt;Sabiendo lo anterior empezamos creando el proyecto en Visual Studio 2019.&lt;/p&gt;

&lt;p&gt;Una vez creado el proyecto de ASP.NET Core 3.0 MVC&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--dpYCCX_B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qq2b5rmde5hurpgwa0ub.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--dpYCCX_B--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qq2b5rmde5hurpgwa0ub.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El siguiente paso es crear los modelos que necesitaremos para logar persistencia de información en la base de datos en memoria.&lt;/p&gt;

&lt;p&gt;Para este ejemplo utilizaremos la relación de modelos Álbum y Género donde un Álbum puede contener un Artista y un Artista puede pertenecer a múltiples Álbumes, vamos a utilizar el enfoque Code First este es el enfoque que nos conviene en este escenario.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--f5uW-9RD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/q9brsi2s4u2ve4qvrd9f.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--f5uW-9RD--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/q9brsi2s4u2ve4qvrd9f.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--JoX19rdO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/7jidf4ezvbtjntwzkg2z.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--JoX19rdO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/7jidf4ezvbtjntwzkg2z.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Después de la creación de los modelos y enfocarnos en el código primero vamos a instalar el nuget de Entity Framework Core InMemory para después crear el Contexto de Datos y decirle a Entity Framework Core que proceda a mapear nuestros modelos.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--RJLEJ31K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qc67ffx1hovc66xh2pjc.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--RJLEJ31K--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/qc67ffx1hovc66xh2pjc.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ahora creamos el Contexto, creamos una carpeta llamada DataContext y dentro de esta creamos una nueva clase llamada AppDbContext la cuál hereda de la clase DbContext que está definida dentro del nuget de Entity Framework Core claro sin olvidar agregar la referencia a Microsoft.EntityFrameworkCore.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EK889LZN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3bshu75q36rstvpfzqn4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EK889LZN--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/3bshu75q36rstvpfzqn4.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;El siguiente paso es dar de alta el servicio en el método ConfigureServices de la clase Startup.cs aquí debemos decirle al servicio que utilize el contexto que acabamos de crear y decirle que la base de datos será en memoria.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--3wbzX56---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/548kjfhkf2kaqwuj419p.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--3wbzX56---/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/548kjfhkf2kaqwuj419p.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Luego debemos crear una clase static y un método static void para inicializar la base de datos. Debido a que no podemos hacerlo por medio de sql y el enfoque para este escenario es code first debemos apoyarnos de Entity Framework Core para persistir de datos para que cuando se cree la base datos en memoria seguidamente empiece el proceso de inicializar y poblar de información las tablas de la base de datos.&lt;br&gt;
Situados dentro de la carpeta DataContext crearemos una nueva carpeta llamada Data y dentro de Data vamos a crear una nueva clase llamada DbInitializer no olvidar definirla como static y seguidamente crear el método public static void Initialize(IServiceProvider serviceProvider) el parámetro que recibe este método es una interfaz que utilizaremos para inyectar la dependencia y abstraer la implementación para utilizar el contexto de datos, aprovecharemos que ASP.NET Core admite el patrón de diseño de software de inyección de dependencias, técnica para lograr la Inversión de Control (IoC) entre las clases y sus dependencias.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tfeB1YNu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ugqmpdunj4blyq6640qo.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tfeB1YNu--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/ugqmpdunj4blyq6640qo.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--xa9RztVg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/sqnidygw38vnzki34re7.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--xa9RztVg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/sqnidygw38vnzki34re7.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seguidamente vamos a modificar el código del método Main en la clase Program.cs necesitamos obtener el IWebhost que alojará la aplicación, lo asignamos a un objeto anónimo, luego necesitamos acceder a un servicio con alcance en el inicio (Startup) para ejecutar tareas de inicialización y por último debemos crear la instancia del contexto en la capa de servicios e invocar al método DbInitializer.Initialize(services) enviando como parámetro el servicio de inicialización.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--39RKlcX_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/nvydox0k9vvslpvf1bg4.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--39RKlcX_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/nvydox0k9vvslpvf1bg4.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Ya estamos cerca del final, tenemos la configuración lista para acceder a los datos de una base de datos en memoria, vamos al HomeController y utilizaremos el contexto de datos para listar los datos y mostrarlos en la vista Index.&lt;/p&gt;

&lt;p&gt;Creamos una propiedad de lectura de tipo AppDbContext, inyectamos la dependencia en el constructor del HomeController y recuperamos la lista de Álbumes y su relación con el modelo Artista asignando el resultado a un objeto anónimo que le pasaremos a la vista.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u1nmhQmJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/iqsfq90deklfm6ck0c6a.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u1nmhQmJ--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/iqsfq90deklfm6ck0c6a.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Tipamos nuestra vista Index para que reciba una lista de Álbumes y luego agregaremos este código para mostrar en una tabla de html las propiedades de nuestra lista de Álbumes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--a04GctAS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/eyjnsiijzc7hymtba885.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--a04GctAS--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/eyjnsiijzc7hymtba885.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Al compilar y ejecutar nuestra aplicación web el resultado es el siguiente.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--lEror2kg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/r9dubaggme6z72wv1uzn.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--lEror2kg--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/r9dubaggme6z72wv1uzn.PNG" alt="Alt Text"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Link al repositorio en GitHub&lt;br&gt;
&lt;a href="https://github.com/EbarriosCode/Base-de-Datos-en-Memoria-Net-Core-3.0-MVC-EFCore"&gt;https://github.com/EbarriosCode/Base-de-Datos-en-Memoria-Net-Core-3.0-MVC-EFCore&lt;/a&gt;&lt;/p&gt;

</description>
      <category>csharp</category>
      <category>dotnet</category>
      <category>database</category>
    </item>
  </channel>
</rss>
