Almacenamiento En Caché En Entity Framework Core Usando NCache

En este artículo se explicará cómo integrar Entity Framework Core con un motor de almacenamiento en caché usando NCache. El artículo brindará un ejemplo práctico de cómo podríamos configurar nuestro Entity Framework Core en una aplicación de consola y cómo utilizar NCache para realizar solicitudes más rápidas a la base de datos con su caché distribuida en memoria nativa.

¿Qué es Entity Framework Core?

Entity Framework Core es el ORM (Object Relational Mapper) más reciente de Microsoft, que ayuda a las aplicaciones de software a mapear, conectar y administrar entidades en una amplia gama de bases de datos. Entity Framework Core es de código abierto y multiplataforma, siendo el 1 ORM principal utilizado por software que utiliza tecnologías de Microsoft.

Al momento de escribir este artículo, Entity Framework Core ofrece dos formas de conectar sus entidades a la base de datos:

  • Code First, escribiendo primero las entidades de su proyecto y luego reflejando esos objetos en la base de datos;
  • Base de datos Primero, crea primero tu base de datos y luego genera las entidades de tu proyecto.

¿Qué es NCache?

NCache también es un software de código abierto y multiplataforma. Su servidor de caché ofrece una caché distribuida en memoria escalable para .NET, Java, Scala, Python y Node.js. Como este artículo se centrará en las tecnologías .NET, podemos usar NCache para aprovechar los siguientes usos:

  • almacenamiento de estado de sesión ASP.NET;
  • Caché de estado de vista de ASP.NET;
  • Caché de salida ASP.NET;
  • Caché de Entity Framework;
  • Caché de segundo nivel de NHibernate.

NCache con Entity Framework Core

Podemos agregar una capa de caché entre Entity Framework Core y nuestra aplicación con NCache, esto mejoraría el tiempo de respuesta de nuestras consultas y reduciría la necesidad de viajes de ida y vuelta a la base de datos en la medida en que obtendríamos datos de las entidades almacenadas en caché de NCache. 

Opciones de almacenamiento en caché

NCache brinda la posibilidad de tener un conjunto diferente de opciones para enviar desde cada solicitud, lo que significa que podemos usar el caché de manera diferente según el conjunto de resultados con el que estamos trabajando para ser más eficientes.

Como vamos a ver en los ejemplos prácticos, debemos proporcionar las opciones de caché en cada solicitud a NCache y esas opciones son las siguientes:

  • AbsoluteExpirationTime, establece el tiempo absoluto en que caducará el elemento almacenado en caché;
    • Tipo de datos: fecha y hora
  • CreateDbDependency, crea o no una dependencia de base de datos a partir del conjunto de resultados;
    • Tipo de dato: booleano
  • ExpirationType, establece el tipo de vencimiento:
    • Absoluto,
    • Corredizo,
    • Ninguna.
  • IsSyncEnabled, establece si los elementos caducados deben volver a sincronizarse con la base de datos.
    • Tipo de dato: booleano
  • Prioridad, establece la prioridad relativa de los elementos almacenados en la memoria caché.
    • Normal,
    • Bajo,
    • Debajo de lo normal,
    • Por encima de lo normal,
    • Alto,
    • no extraíble,
    • Defecto
  • QueryIdentifier, identificador del conjunto de resultados.
    • Tipo de datos: cadena.
  • ReadThruProvider, establece el proveedor de lectura para la sincronización de caché
    • Tipo de datos: cadena
  • SlidingExpirationTime, establece el tiempo de vencimiento deslizante
    • Tipo de datos: Intervalo de tiempo
  • StoreAs, establece cómo se almacenarán los elementos.
    • Recopilación
    • Entidades separadas

Llamadas diferidas

NCache tiene sus propios métodos de extensión para que podamos trabajar con llamadas diferidas de Entity Framework Core y están en 3 grupos diferentes:

  • Operadores Agregados, realizando operaciones contra cobranzas. Se puede usar con los métodos FromCache y FromCacheOnly .
    • Promedio diferido.
      • Productos.Seleccionar(o => o.PrecioUnitario).PromedioDiferido()
    • Recuento diferido
      • Clientes.Seleccionar(c => c.País).AgruparPor(c => c).Recuento diferido()
    • DiferidoMin
      • Pedidos.Dónde(o => o.CustomerId == "VINET").Select(o => o.RequiredDate).DeferredMin()
    • DiferidoMax
      • Pedidos.Select(o => o.RequiredDate).DeferredMax()
    • Suma diferida
      • OrderDetails.Select(o => o.UnitPrice).DeferredSum()
  • Operadores de elementos, haciendo operaciones para elementos individuales. Solo se puede usar con el método FromCache .
    • DeferredElementAtOrDefault
      • Customers.DeferredElementAtOrDefault(c => c.City == "Londres")
    • DeferredFirst
      • Customers.DeferredFirst(c => c.ContactTitle == "Representante de ventas")
    • DeferredFirstOrDefault
      • Customers.DeferredFirstOrDefault(c => c.ContactTitle == "Representante de ventas")
    • DiferidoÚltimo
      • Clientes.ÚltimoAplazado(c => c.Ciudad == "Londres")
    • DeferredLastOrDefault
      • Customers.DeferredLastOrDefault(c => c.City == "Londres")
    • DiferidoSoltero
      • Clientes.SolteroDiferido(c => c.IdCliente == "ALFKI")
    • DeferredSingleOrDefault
      • Customers.DeferredSingleOrDefault(c => c.CustomerId == "ANATR")
  • Otros. Solo se puede usar con el método FromCache .
    • DiferidoTodo
      • Productos.DeferredAll(expresión)
    • DeferredLongCount
      • Productos.DeferredLongCount()
    • DeferredContains
      • Products.DeferredContains (nuevos productos { ProductId = 1 })

Métodos de almacenamiento en caché

Métodos de NCache para manipular objetos almacenados en caché:

  • Insertar

Inserta un solo objeto en el caché con sus propias opciones. Devuelve la clave de caché

var customerEntity = new Customers
   {
       CustomerId = "HANIH",
       ContactName = "Hanih Moos",
       ContactTitle = "Sales Representative ",
       CompanyName = "Blauer See Delikatessen"
   };

   //Add customer entity to database
   database.Customers.Add(customerEntity);
   database.SaveChanges();

   //Caching options for cache
   var options = new CachingOptions
   {
       QueryIdentifier = "CustomerEntity",
       Priority = Runtime.CacheItemPriority.Default,
   };

   //Add customer entity to cache
   Cache cache = database.GetCache();

   cache.Insert(customerEntity, out string cacheKey, options);
  • Quitar (entidad objeto)

Elimina un solo objeto de la memoria caché.

var cust = new Customers
  {
      CustomerId = "HANIH",
      ContactName = "Hanih Moos",
      ContactTitle = "Sales Representative",
      CompanyName = "Blauer See Delikatessen"
  };

  cache.Remove(cust);
  • Eliminar (cadena cacheKey)

Eliminar un objeto pasando su clave de caché

cache.Remove("cacheKey");
  • RemoveByQueryIdentifier

Eliminar todas las entidades del caché que coincidan con el identificador de consulta

Tag tag = new Tag(queryIdentifier);
cache.RemoveByQueryIdentifier(tag);

Almacenamiento en caché con métodos de extensión NCache 

Métodos de extensión de NCache para Entity Framework Core

  • Obtener Caché

Obtiene la instancia de caché.

using (var context = new NorthwindContext())
{
Cache cache = context.GetCache();
}
  • DesdeCaché

Si hay datos almacenados en caché, se devolverán sin pasar por la fuente de datos. Si no hay datos almacenados en caché, los datos se devolverán desde la fuente de datos y se almacenarán en caché.

var options = new CachingOptions
{
    StoreAs = StoreAs.SeperateEntities
};

var resultSet = (from cust in context.Customers
                 where cust.CustomerId == 10
                 select cust).FromCache(options);

Devolver la cacheKey del conjunto de resultados

var options = new CachingOptions
{
    StoreAs = StoreAs.Collection
};

var resultSet = (from cust in context.Customers
                where cust.CustomerId == 10
                select cust).FromCache(out string cacheKey, options);
  • Cargar en caché

Cada solicitud va primero a la fuente de datos, almacena en caché su conjunto de resultados y lo devuelve.

var options = new CachingOptions
    {
        StoreAs = StoreAs.SeperateEntities
    };

    var resultSet = (from custOrder in context.Orders
                     where custOrder.Customer.CustomerId == 10
                     select custOrder)).LoadIntoCache(options);

Devolver la clave de caché del conjunto de resultados

var options = new CachingOptions
{
    StoreAs = StoreAs.Collection
};

var resultSet = (from custOrder in context.Orders
                 where custOrder.Customer.CustomerId == 10
                 select custOrder)).LoadIntoCache(out string cacheKey, options);
  • DesdeCacheOnly

Nunca va a la fuente de datos. La solicitud solo va a la memoria caché; si no se almacena ningún resultado coincidente, se devolverá como un conjunto de resultados vacío.

Las inclusiones y las uniones no son compatibles con FromCacheOnly().

var resultSet = (from cust in context.Customers
                 where cust.CustomerId == someCustomerId
                 select cust).FromCacheOnly();

Implementación de NCache paso a paso

0. Requisitos previos

1. La aplicación

  • Cree una aplicación de consola C# dirigida a .NET 6.0 e instale los siguientes paquetes nugets:
    • EntityFrameworkCore.NCache
    • Microsoft.EntityFrameworkCore.SqlServer
    • Microsoft.EntityFrameworkCore.SqlServer.Diseño
    • Microsoft.EntityFrameworkCore.Herramientas
    • System.Data.SqlClient
    • System.Collections
  • Los siguientes archivos NCache se insertarán en su proyecto después de instalar los paquetes Nuget.
    • cliente.ncconf
    • config.ncconf
    • tls.ncconf

2. Modelos

Para esta muestra, se creó una relación de modelo muy simple, de la siguiente manera:

  • Producto
[Serializable]
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
    public List<Transaction> Transactions { get; set; }
    public Store Store { get; set; }
    public int? StoreId { get; set; }
}
  • Tienda
[Serializable]
public class Store
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Location { get; set; }
    public ICollection<Product> AvailableProducts { get; set; }
    public ICollection<Consumer> RegularConsumers { get; set; }
}
  • Consumidor
[Serializable]
public class Consumer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Store FavouriteStore { get; set; }
    public int? FavouriteStoreId { get; set; }
    public List<Transaction> Transactions { get; set; }
}
  • Transacción
[Serializable]
public class Transaction
{
     public int Id { get; set; }

     public Consumer Consumer { get; set; }
     public int ConsumerId { get; set; }

     public Product Product { get; set; }
     public int ProductId { get; set; }
}
  • DBContexto

La clase DBContext tiene configuraciones de inicialización de NCache y la relación del modelo.

public class SampleDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // configure cache with SQLServer DependencyType and CacheInitParams
        CacheConnectionOptions initParams = new CacheConnectionOptions();
        initParams.RetryInterval = new TimeSpan(0, 0, 5);
        initParams.ConnectionRetries = 2;
        initParams.ConnectionTimeout = new TimeSpan(0, 0, 5);
        initParams.AppName = "appName";
        initParams.CommandRetries = 2;
        initParams.CommandRetryInterval = new TimeSpan(0, 0, 5);
        initParams.Mode = IsolationLevel.Default;

        NCacheConfiguration.Configure("democache", DependencyType.SqlServer, initParams);

        optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-AT3H2E;Initial Catalog=sampleDatabase;Integrated Security=True");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Store>()
            .HasMany(x => x.AvailableProducts)
            .WithOne(x => x.Store)
            .HasForeignKey(x => x.StoreId)
            .IsRequired(false)
            .OnDelete(DeleteBehavior.NoAction);

        modelBuilder.Entity<Store>()
            .HasMany(x => x.RegularConsumers)
            .WithOne(x => x.FavouriteStore)
            .HasForeignKey(x => x.FavouriteStoreId)
            .IsRequired(false)
            .OnDelete(DeleteBehavior.NoAction);

        modelBuilder.Entity<Transaction>()
            .HasOne(x => x.Consumer)
            .WithMany(x => x.Transactions)
            .HasForeignKey(x => x.ConsumerId)
            .IsRequired(false);

        modelBuilder.Entity<Transaction>()
            .HasOne(x => x.Product)
            .WithMany(x => x.Transactions)
            .HasForeignKey(x => x.ProductId)
            .IsRequired(false);
    }

    public DbSet<Store> Stores { get; set; }
    public DbSet<Consumer> Consumers { get; set; }
    public DbSet<Product> Products { get; set; }
    public DbSet<Transaction> Transactions { get; set; }
}

3. Métodos NCache

Aquí está la clase con los métodos NCache necesarios para manipular objetos desde y hacia el caché.

public class NCacheExtensions
{
    private SampleDbContext Database { get; set; }
    private CachingOptions CachingOptions { get; set; }
    private Cache Cache { get; set; }

    public NCacheExtensions(SampleDbContext database)
    {
        this.Database = database;
        this.CachingOptions = new CachingOptions
        {
            QueryIdentifier = "Sample QueryIdentifier",
            Priority = Alachisoft.NCache.Runtime.CacheItemPriority.Default,
            CreateDbDependency = false,
            StoreAs = StoreAs.Collection
        };

        Cache = database.GetCache();
    }

    public string AddSingleEntity<T>(T entity)
    {
        Cache.Insert(entity, out string cacheKey, this.CachingOptions);
        return cacheKey;
    }
    public void RemoveSingleEntity<T>(T entity)
    {
        Cache.Remove(entity);
    }
    public void RemoveSingleEntity(string cacheKey)
    {
        Cache.Remove(cacheKey);
    }
    public void RemoveByQueryIdentifier(string queryIdentifier)
    {
        var tag = new Tag(queryIdentifier);
        Cache.RemoveByQueryIdentifier(tag);
    }

    public IEnumerable<Consumer> GetAllConsumersFromCache(CachingOptions cachingOptions)
    {
        return Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).FromCache(cachingOptions);
    }
    public async Task<IEnumerable<Consumer>> GetAllConsumersFromCacheAsync(CachingOptions cachingOptions)
    {
        return await Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).FromCacheAsync(cachingOptions);
    }
    public IEnumerable<Consumer> LoadAllConsumersIntoCache(CachingOptions cachingOptions)
    {
        return Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).LoadIntoCache(cachingOptions);
    }
    public async Task<IEnumerable<Consumer>> LoadAllConsumersIntoCacheAsync(CachingOptions cachingOptions)
    {
        return await Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).LoadIntoCacheAsync(cachingOptions);
    }
    public IEnumerable<Consumer> GetAllConsumersFromCacheOnly(CachingOptions cachingOptions)
    {
        return Database.Consumers.FromCacheOnly();
    }
}

4.La clase program.cs

Aquí tenemos el punto de inicio de nuestra aplicación de consola. Con un ejemplo sobre cómo conectarse a NCache y usar sus métodos de extensión que se proporcionaron anteriormente.

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        using (var context = new SampleDbContext())
        {
            var cachedContext = new NCacheExtensions(context);

            Console.WriteLine("start LoadAllConsumersIntoCache " + DateTime.Now.ToString("HH:mm:ss.f"));
            var loadInCache = cachedContext.LoadAllConsumersIntoCache(new CachingOptions { StoreAs = StoreAs.Collection, QueryIdentifier = "Sample QueryIdentifier" });
            Console.WriteLine("finish LoadAllConsumersIntoCache" + DateTime.Now.ToString("HH:mm:ss.f"));

            Console.WriteLine("start GetAllConsumersFromCache " + DateTime.Now.ToString("HH:mm:ss.f"));
            var getFromCache = cachedContext.GetAllConsumersFromCache(new CachingOptions { Priority = Alachisoft.NCache.Runtime.CacheItemPriority.Default });
            Console.WriteLine("finish GetAllConsumersFromCache " + DateTime.Now.ToString("HH:mm:ss.f"));

            Console.WriteLine("start load from DBContext " + DateTime.Now.ToString("HH:mm:ss.f"));
            var getFromDb = context.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product);
            Console.WriteLine("finishg load from DBContext " + DateTime.Now.ToString("HH:mm:ss.f"));

            var cachedEntity = cachedContext.AddSingleEntity<Consumer>(getFromDb.FirstOrDefault());
            Console.WriteLine("cache key: " + cachedEntity);

            cachedContext.RemoveSingleEntity(cachedEntity);
            cachedContext.RemoveByQueryIdentifier("Sample QueryIdentifier");

        }
    }
}

Funcionamiento de la aplicación:

¡Felicidades! Ha utilizado con éxito NCache para almacenar en caché sus datos de Entity Framework Core.

Esta historia se publicó originalmente en https://www.c-sharpcorner.com/article/caching-in-entity-framework-core-using-ncache/ 

#ncache #entity-framework 

What is GEEK

Buddha Community

Almacenamiento En Caché En Entity Framework Core Usando NCache
Einar  Hintz

Einar Hintz

1602560783

jQuery Ajax CRUD in ASP.NET Core MVC with Modal Popup

In this article, we’ll discuss how to use jQuery Ajax for ASP.NET Core MVC CRUD Operations using Bootstrap Modal. With jQuery Ajax, we can make HTTP request to controller action methods without reloading the entire page, like a single page application.

To demonstrate CRUD operations – insert, update, delete and retrieve, the project will be dealing with details of a normal bank transaction. GitHub repository for this demo project : https://bit.ly/33KTJAu.

Sub-topics discussed :

  • Form design for insert and update operation.
  • Display forms in modal popup dialog.
  • Form post using jQuery Ajax.
  • Implement MVC CRUD operations with jQuery Ajax.
  • Loading spinner in .NET Core MVC.
  • Prevent direct access to MVC action method.

Create ASP.NET Core MVC Project

In Visual Studio 2019, Go to File > New > Project (Ctrl + Shift + N).

From new project window, Select Asp.Net Core Web Application_._

Image showing how to create ASP.NET Core Web API project in Visual Studio.

Once you provide the project name and location. Select Web Application(Model-View-Controller) and uncheck HTTPS Configuration. Above steps will create a brand new ASP.NET Core MVC project.

Showing project template selection for .NET Core MVC.

Setup a Database

Let’s create a database for this application using Entity Framework Core. For that we’ve to install corresponding NuGet Packages. Right click on project from solution explorer, select Manage NuGet Packages_,_ From browse tab, install following 3 packages.

Showing list of NuGet Packages for Entity Framework Core

Now let’s define DB model class file – /Models/TransactionModel.cs.

public class TransactionModel
{
    [Key]
    public int TransactionId { get; set; }

    [Column(TypeName ="nvarchar(12)")]
    [DisplayName("Account Number")]
    [Required(ErrorMessage ="This Field is required.")]
    [MaxLength(12,ErrorMessage ="Maximum 12 characters only")]
    public string AccountNumber { get; set; }

    [Column(TypeName ="nvarchar(100)")]
    [DisplayName("Beneficiary Name")]
    [Required(ErrorMessage = "This Field is required.")]
    public string BeneficiaryName { get; set; }

    [Column(TypeName ="nvarchar(100)")]
    [DisplayName("Bank Name")]
    [Required(ErrorMessage = "This Field is required.")]
    public string BankName { get; set; }

    [Column(TypeName ="nvarchar(11)")]
    [DisplayName("SWIFT Code")]
    [Required(ErrorMessage = "This Field is required.")]
    [MaxLength(11)]
    public string SWIFTCode { get; set; }

    [DisplayName("Amount")]
    [Required(ErrorMessage = "This Field is required.")]
    public int Amount { get; set; }

    [DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}")]
    public DateTime Date { get; set; }
}

C#Copy

Here we’ve defined model properties for the transaction with proper validation. Now let’s define  DbContextclass for EF Core.

#asp.net core article #asp.net core #add loading spinner in asp.net core #asp.net core crud without reloading #asp.net core jquery ajax form #asp.net core modal dialog #asp.net core mvc crud using jquery ajax #asp.net core mvc with jquery and ajax #asp.net core popup window #bootstrap modal popup in asp.net core mvc. bootstrap modal popup in asp.net core #delete and viewall in asp.net core #jquery ajax - insert #jquery ajax form post #modal popup dialog in asp.net core #no direct access action method #update #validation in modal popup

Hertha  Mayer

Hertha Mayer

1602668764

Announcing Entity Framework Core (EF Core) 5 RC2

Today, the Entity Framework Core team announces the second release candidate (RC2) of EF Core 5.0. This is a feature complete release candidate of EF Core 5.0 and ships with a “go live” license. You are supported using it in production. This is a great opportunity to start using EF Core 5.0 early while there is still time to fix remaining issues. We’re looking for reports of any remaining critical bugs that should be fixed before the final release.

Prerequisites

EF Core 5.0 will not run on .NET Standard 2.0 platforms, including .NET Framework.

How to get EF Core 5.0 Release Candidate 2

EF Core is distributed exclusively as a set of NuGet packages. For example, to add the SQL Server provider to your project, you can use the following command using the dotnet tool:

dotnet add package Microsoft.EntityFrameworkCore.SqlServer --version 5.0.0-rc.2.20475.6

#.net #.net core #.net framework #asp.net #c# #entity framework #announcement #asp.net core #entity framework core

Ken  Mueller

Ken Mueller

1595261580

Entity Framework Core in ASP.NET Core 3.1

This article will be covering in detail the implementation of Entity Framework Core in ASP.NET Core Web API. We will learn about entity framework core in details i.e. what, how & why and see how to use it in ASP.NET Core Web API to implement CRUD operations. Though here we will be using entity framework in ASP.NET Core this can be implemented even in .NET Framework for your data persistence. I hope you will join me on this and go through step by step demonstration on implementing entity framework core in ASP.NET Core Web API.

Introduction to Entity Framework Core

ASP.NET Core Entity Framework

Entity Framework has been around since 2008 which has improved over the years. Entity framework core was introduced for .NET Core based applications. It is an open-source object-relational mapper (ORM) built over ADO.NET and an official data access platform from Microsoft. Entity framework core has been rewritten from scratch to make it lightweight, flexible & achieve better performance.

In the absence of an ORM typically lots of code have to be written to perform CRUD operations with the database. using an ORM like entity framework can reduce the number of lines of code to be written for database interactions. Typical ORM will work on classes & database tables of similar structure but entity framework core implements mappings which makes it a lot more flexible i.e. in case table & class does not match then mappings can be exercised to get from objects to tables.

Entity framework core can work with wide variety of databases. Microsoft provides rich providers for SQL Server & SQLite and there are many other third party providers some commercial and some from community.

How does entity framework core works?

How Entity Framework Works

  1. Define domain classes & configure entity framework DbContext API along with mappings to let entity framework work how this class maps to the database schema.
  2. Write LINQ to objects to fetch data from the database.
  3. Based on mappings & database provider configured entity framework will translate queries into SQL that’s understood by the database.
  4. The query is executed and the object is populated with data.
  5. Data in objects can be modified, deleted or new records can be added to the list & once done call DbContext.saveChanges from EF API to save data back to the database.
  6. The entity framework will generate the required SQL statements to save data back to the database.

#programming #.net core #asp.net core 3.1 #entity framework #entity framework core

Almacenamiento En Caché En Entity Framework Core Usando NCache

En este artículo se explicará cómo integrar Entity Framework Core con un motor de almacenamiento en caché usando NCache. El artículo brindará un ejemplo práctico de cómo podríamos configurar nuestro Entity Framework Core en una aplicación de consola y cómo utilizar NCache para realizar solicitudes más rápidas a la base de datos con su caché distribuida en memoria nativa.

¿Qué es Entity Framework Core?

Entity Framework Core es el ORM (Object Relational Mapper) más reciente de Microsoft, que ayuda a las aplicaciones de software a mapear, conectar y administrar entidades en una amplia gama de bases de datos. Entity Framework Core es de código abierto y multiplataforma, siendo el 1 ORM principal utilizado por software que utiliza tecnologías de Microsoft.

Al momento de escribir este artículo, Entity Framework Core ofrece dos formas de conectar sus entidades a la base de datos:

  • Code First, escribiendo primero las entidades de su proyecto y luego reflejando esos objetos en la base de datos;
  • Base de datos Primero, crea primero tu base de datos y luego genera las entidades de tu proyecto.

¿Qué es NCache?

NCache también es un software de código abierto y multiplataforma. Su servidor de caché ofrece una caché distribuida en memoria escalable para .NET, Java, Scala, Python y Node.js. Como este artículo se centrará en las tecnologías .NET, podemos usar NCache para aprovechar los siguientes usos:

  • almacenamiento de estado de sesión ASP.NET;
  • Caché de estado de vista de ASP.NET;
  • Caché de salida ASP.NET;
  • Caché de Entity Framework;
  • Caché de segundo nivel de NHibernate.

NCache con Entity Framework Core

Podemos agregar una capa de caché entre Entity Framework Core y nuestra aplicación con NCache, esto mejoraría el tiempo de respuesta de nuestras consultas y reduciría la necesidad de viajes de ida y vuelta a la base de datos en la medida en que obtendríamos datos de las entidades almacenadas en caché de NCache. 

Opciones de almacenamiento en caché

NCache brinda la posibilidad de tener un conjunto diferente de opciones para enviar desde cada solicitud, lo que significa que podemos usar el caché de manera diferente según el conjunto de resultados con el que estamos trabajando para ser más eficientes.

Como vamos a ver en los ejemplos prácticos, debemos proporcionar las opciones de caché en cada solicitud a NCache y esas opciones son las siguientes:

  • AbsoluteExpirationTime, establece el tiempo absoluto en que caducará el elemento almacenado en caché;
    • Tipo de datos: fecha y hora
  • CreateDbDependency, crea o no una dependencia de base de datos a partir del conjunto de resultados;
    • Tipo de dato: booleano
  • ExpirationType, establece el tipo de vencimiento:
    • Absoluto,
    • Corredizo,
    • Ninguna.
  • IsSyncEnabled, establece si los elementos caducados deben volver a sincronizarse con la base de datos.
    • Tipo de dato: booleano
  • Prioridad, establece la prioridad relativa de los elementos almacenados en la memoria caché.
    • Normal,
    • Bajo,
    • Debajo de lo normal,
    • Por encima de lo normal,
    • Alto,
    • no extraíble,
    • Defecto
  • QueryIdentifier, identificador del conjunto de resultados.
    • Tipo de datos: cadena.
  • ReadThruProvider, establece el proveedor de lectura para la sincronización de caché
    • Tipo de datos: cadena
  • SlidingExpirationTime, establece el tiempo de vencimiento deslizante
    • Tipo de datos: Intervalo de tiempo
  • StoreAs, establece cómo se almacenarán los elementos.
    • Recopilación
    • Entidades separadas

Llamadas diferidas

NCache tiene sus propios métodos de extensión para que podamos trabajar con llamadas diferidas de Entity Framework Core y están en 3 grupos diferentes:

  • Operadores Agregados, realizando operaciones contra cobranzas. Se puede usar con los métodos FromCache y FromCacheOnly .
    • Promedio diferido.
      • Productos.Seleccionar(o => o.PrecioUnitario).PromedioDiferido()
    • Recuento diferido
      • Clientes.Seleccionar(c => c.País).AgruparPor(c => c).Recuento diferido()
    • DiferidoMin
      • Pedidos.Dónde(o => o.CustomerId == "VINET").Select(o => o.RequiredDate).DeferredMin()
    • DiferidoMax
      • Pedidos.Select(o => o.RequiredDate).DeferredMax()
    • Suma diferida
      • OrderDetails.Select(o => o.UnitPrice).DeferredSum()
  • Operadores de elementos, haciendo operaciones para elementos individuales. Solo se puede usar con el método FromCache .
    • DeferredElementAtOrDefault
      • Customers.DeferredElementAtOrDefault(c => c.City == "Londres")
    • DeferredFirst
      • Customers.DeferredFirst(c => c.ContactTitle == "Representante de ventas")
    • DeferredFirstOrDefault
      • Customers.DeferredFirstOrDefault(c => c.ContactTitle == "Representante de ventas")
    • DiferidoÚltimo
      • Clientes.ÚltimoAplazado(c => c.Ciudad == "Londres")
    • DeferredLastOrDefault
      • Customers.DeferredLastOrDefault(c => c.City == "Londres")
    • DiferidoSoltero
      • Clientes.SolteroDiferido(c => c.IdCliente == "ALFKI")
    • DeferredSingleOrDefault
      • Customers.DeferredSingleOrDefault(c => c.CustomerId == "ANATR")
  • Otros. Solo se puede usar con el método FromCache .
    • DiferidoTodo
      • Productos.DeferredAll(expresión)
    • DeferredLongCount
      • Productos.DeferredLongCount()
    • DeferredContains
      • Products.DeferredContains (nuevos productos { ProductId = 1 })

Métodos de almacenamiento en caché

Métodos de NCache para manipular objetos almacenados en caché:

  • Insertar

Inserta un solo objeto en el caché con sus propias opciones. Devuelve la clave de caché

var customerEntity = new Customers
   {
       CustomerId = "HANIH",
       ContactName = "Hanih Moos",
       ContactTitle = "Sales Representative ",
       CompanyName = "Blauer See Delikatessen"
   };

   //Add customer entity to database
   database.Customers.Add(customerEntity);
   database.SaveChanges();

   //Caching options for cache
   var options = new CachingOptions
   {
       QueryIdentifier = "CustomerEntity",
       Priority = Runtime.CacheItemPriority.Default,
   };

   //Add customer entity to cache
   Cache cache = database.GetCache();

   cache.Insert(customerEntity, out string cacheKey, options);
  • Quitar (entidad objeto)

Elimina un solo objeto de la memoria caché.

var cust = new Customers
  {
      CustomerId = "HANIH",
      ContactName = "Hanih Moos",
      ContactTitle = "Sales Representative",
      CompanyName = "Blauer See Delikatessen"
  };

  cache.Remove(cust);
  • Eliminar (cadena cacheKey)

Eliminar un objeto pasando su clave de caché

cache.Remove("cacheKey");
  • RemoveByQueryIdentifier

Eliminar todas las entidades del caché que coincidan con el identificador de consulta

Tag tag = new Tag(queryIdentifier);
cache.RemoveByQueryIdentifier(tag);

Almacenamiento en caché con métodos de extensión NCache 

Métodos de extensión de NCache para Entity Framework Core

  • Obtener Caché

Obtiene la instancia de caché.

using (var context = new NorthwindContext())
{
Cache cache = context.GetCache();
}
  • DesdeCaché

Si hay datos almacenados en caché, se devolverán sin pasar por la fuente de datos. Si no hay datos almacenados en caché, los datos se devolverán desde la fuente de datos y se almacenarán en caché.

var options = new CachingOptions
{
    StoreAs = StoreAs.SeperateEntities
};

var resultSet = (from cust in context.Customers
                 where cust.CustomerId == 10
                 select cust).FromCache(options);

Devolver la cacheKey del conjunto de resultados

var options = new CachingOptions
{
    StoreAs = StoreAs.Collection
};

var resultSet = (from cust in context.Customers
                where cust.CustomerId == 10
                select cust).FromCache(out string cacheKey, options);
  • Cargar en caché

Cada solicitud va primero a la fuente de datos, almacena en caché su conjunto de resultados y lo devuelve.

var options = new CachingOptions
    {
        StoreAs = StoreAs.SeperateEntities
    };

    var resultSet = (from custOrder in context.Orders
                     where custOrder.Customer.CustomerId == 10
                     select custOrder)).LoadIntoCache(options);

Devolver la clave de caché del conjunto de resultados

var options = new CachingOptions
{
    StoreAs = StoreAs.Collection
};

var resultSet = (from custOrder in context.Orders
                 where custOrder.Customer.CustomerId == 10
                 select custOrder)).LoadIntoCache(out string cacheKey, options);
  • DesdeCacheOnly

Nunca va a la fuente de datos. La solicitud solo va a la memoria caché; si no se almacena ningún resultado coincidente, se devolverá como un conjunto de resultados vacío.

Las inclusiones y las uniones no son compatibles con FromCacheOnly().

var resultSet = (from cust in context.Customers
                 where cust.CustomerId == someCustomerId
                 select cust).FromCacheOnly();

Implementación de NCache paso a paso

0. Requisitos previos

1. La aplicación

  • Cree una aplicación de consola C# dirigida a .NET 6.0 e instale los siguientes paquetes nugets:
    • EntityFrameworkCore.NCache
    • Microsoft.EntityFrameworkCore.SqlServer
    • Microsoft.EntityFrameworkCore.SqlServer.Diseño
    • Microsoft.EntityFrameworkCore.Herramientas
    • System.Data.SqlClient
    • System.Collections
  • Los siguientes archivos NCache se insertarán en su proyecto después de instalar los paquetes Nuget.
    • cliente.ncconf
    • config.ncconf
    • tls.ncconf

2. Modelos

Para esta muestra, se creó una relación de modelo muy simple, de la siguiente manera:

  • Producto
[Serializable]
public class Product
{
    public int Id { get; set; }
    public string Name { get; set; }
    public double Price { get; set; }
    public List<Transaction> Transactions { get; set; }
    public Store Store { get; set; }
    public int? StoreId { get; set; }
}
  • Tienda
[Serializable]
public class Store
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Location { get; set; }
    public ICollection<Product> AvailableProducts { get; set; }
    public ICollection<Consumer> RegularConsumers { get; set; }
}
  • Consumidor
[Serializable]
public class Consumer
{
    public int Id { get; set; }
    public string Name { get; set; }
    public Store FavouriteStore { get; set; }
    public int? FavouriteStoreId { get; set; }
    public List<Transaction> Transactions { get; set; }
}
  • Transacción
[Serializable]
public class Transaction
{
     public int Id { get; set; }

     public Consumer Consumer { get; set; }
     public int ConsumerId { get; set; }

     public Product Product { get; set; }
     public int ProductId { get; set; }
}
  • DBContexto

La clase DBContext tiene configuraciones de inicialización de NCache y la relación del modelo.

public class SampleDbContext : DbContext
{
    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    {
        // configure cache with SQLServer DependencyType and CacheInitParams
        CacheConnectionOptions initParams = new CacheConnectionOptions();
        initParams.RetryInterval = new TimeSpan(0, 0, 5);
        initParams.ConnectionRetries = 2;
        initParams.ConnectionTimeout = new TimeSpan(0, 0, 5);
        initParams.AppName = "appName";
        initParams.CommandRetries = 2;
        initParams.CommandRetryInterval = new TimeSpan(0, 0, 5);
        initParams.Mode = IsolationLevel.Default;

        NCacheConfiguration.Configure("democache", DependencyType.SqlServer, initParams);

        optionsBuilder.UseSqlServer(@"Data Source=DESKTOP-AT3H2E;Initial Catalog=sampleDatabase;Integrated Security=True");
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Store>()
            .HasMany(x => x.AvailableProducts)
            .WithOne(x => x.Store)
            .HasForeignKey(x => x.StoreId)
            .IsRequired(false)
            .OnDelete(DeleteBehavior.NoAction);

        modelBuilder.Entity<Store>()
            .HasMany(x => x.RegularConsumers)
            .WithOne(x => x.FavouriteStore)
            .HasForeignKey(x => x.FavouriteStoreId)
            .IsRequired(false)
            .OnDelete(DeleteBehavior.NoAction);

        modelBuilder.Entity<Transaction>()
            .HasOne(x => x.Consumer)
            .WithMany(x => x.Transactions)
            .HasForeignKey(x => x.ConsumerId)
            .IsRequired(false);

        modelBuilder.Entity<Transaction>()
            .HasOne(x => x.Product)
            .WithMany(x => x.Transactions)
            .HasForeignKey(x => x.ProductId)
            .IsRequired(false);
    }

    public DbSet<Store> Stores { get; set; }
    public DbSet<Consumer> Consumers { get; set; }
    public DbSet<Product> Products { get; set; }
    public DbSet<Transaction> Transactions { get; set; }
}

3. Métodos NCache

Aquí está la clase con los métodos NCache necesarios para manipular objetos desde y hacia el caché.

public class NCacheExtensions
{
    private SampleDbContext Database { get; set; }
    private CachingOptions CachingOptions { get; set; }
    private Cache Cache { get; set; }

    public NCacheExtensions(SampleDbContext database)
    {
        this.Database = database;
        this.CachingOptions = new CachingOptions
        {
            QueryIdentifier = "Sample QueryIdentifier",
            Priority = Alachisoft.NCache.Runtime.CacheItemPriority.Default,
            CreateDbDependency = false,
            StoreAs = StoreAs.Collection
        };

        Cache = database.GetCache();
    }

    public string AddSingleEntity<T>(T entity)
    {
        Cache.Insert(entity, out string cacheKey, this.CachingOptions);
        return cacheKey;
    }
    public void RemoveSingleEntity<T>(T entity)
    {
        Cache.Remove(entity);
    }
    public void RemoveSingleEntity(string cacheKey)
    {
        Cache.Remove(cacheKey);
    }
    public void RemoveByQueryIdentifier(string queryIdentifier)
    {
        var tag = new Tag(queryIdentifier);
        Cache.RemoveByQueryIdentifier(tag);
    }

    public IEnumerable<Consumer> GetAllConsumersFromCache(CachingOptions cachingOptions)
    {
        return Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).FromCache(cachingOptions);
    }
    public async Task<IEnumerable<Consumer>> GetAllConsumersFromCacheAsync(CachingOptions cachingOptions)
    {
        return await Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).FromCacheAsync(cachingOptions);
    }
    public IEnumerable<Consumer> LoadAllConsumersIntoCache(CachingOptions cachingOptions)
    {
        return Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).LoadIntoCache(cachingOptions);
    }
    public async Task<IEnumerable<Consumer>> LoadAllConsumersIntoCacheAsync(CachingOptions cachingOptions)
    {
        return await Database.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product).LoadIntoCacheAsync(cachingOptions);
    }
    public IEnumerable<Consumer> GetAllConsumersFromCacheOnly(CachingOptions cachingOptions)
    {
        return Database.Consumers.FromCacheOnly();
    }
}

4.La clase program.cs

Aquí tenemos el punto de inicio de nuestra aplicación de consola. Con un ejemplo sobre cómo conectarse a NCache y usar sus métodos de extensión que se proporcionaron anteriormente.

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Hello World!");

        using (var context = new SampleDbContext())
        {
            var cachedContext = new NCacheExtensions(context);

            Console.WriteLine("start LoadAllConsumersIntoCache " + DateTime.Now.ToString("HH:mm:ss.f"));
            var loadInCache = cachedContext.LoadAllConsumersIntoCache(new CachingOptions { StoreAs = StoreAs.Collection, QueryIdentifier = "Sample QueryIdentifier" });
            Console.WriteLine("finish LoadAllConsumersIntoCache" + DateTime.Now.ToString("HH:mm:ss.f"));

            Console.WriteLine("start GetAllConsumersFromCache " + DateTime.Now.ToString("HH:mm:ss.f"));
            var getFromCache = cachedContext.GetAllConsumersFromCache(new CachingOptions { Priority = Alachisoft.NCache.Runtime.CacheItemPriority.Default });
            Console.WriteLine("finish GetAllConsumersFromCache " + DateTime.Now.ToString("HH:mm:ss.f"));

            Console.WriteLine("start load from DBContext " + DateTime.Now.ToString("HH:mm:ss.f"));
            var getFromDb = context.Consumers.Include(x => x.Transactions).ThenInclude(x => x.Product);
            Console.WriteLine("finishg load from DBContext " + DateTime.Now.ToString("HH:mm:ss.f"));

            var cachedEntity = cachedContext.AddSingleEntity<Consumer>(getFromDb.FirstOrDefault());
            Console.WriteLine("cache key: " + cachedEntity);

            cachedContext.RemoveSingleEntity(cachedEntity);
            cachedContext.RemoveByQueryIdentifier("Sample QueryIdentifier");

        }
    }
}

Funcionamiento de la aplicación:

¡Felicidades! Ha utilizado con éxito NCache para almacenar en caché sus datos de Entity Framework Core.

Esta historia se publicó originalmente en https://www.c-sharpcorner.com/article/caching-in-entity-framework-core-using-ncache/ 

#ncache #entity-framework 

Announcing Entity Framework Core (EF Core) 5.0 Preview 8

Today, the Entity Framework Core team announces the eighth and final preview release of EF Core 5.0. The next release will be a release candidate (RC). This release includes table-per-type (TPT) mapping, table-valued functions, SQLite table rebuilds for migrations and much more.

#.net core #c# #entity framework #announcement #entity framework core #csharp