EF.Core utilizar el mismo modelo para asignar a varias tablas

En ADO.NET Entity Framework Core, que podemos utilizar para configurar los atributos modelo de asignación o API Fluido. Un día, me encontré con una nueva demanda, el sistema generará una gran cantidad de datos de todos los días, crear una nueva tabla para almacenar datos todos los días. Por ejemplo, una base de datos como sigue:

Todas las tablas tienen la misma estructura. Por lo tanto, la forma de cambiar el mapa con el fin de evitar la creación de múltiples modelos de hacer?

En este artículo, te voy a mostrar cómo cambiar la asignación de manejar esta situación. También puede utilizar este método para extender más su uso.

Creación de proyecto .NET Core 3.1

Ahora, podemos usar el .NET Core 3.1, que es una versión LTS de .NET Core en el futuro se puede actualizar fácilmente a .NET 5.

Suponiendo que ha instalado la última .NET SDK básico en el equipo. Si no es así, se puede descargar desde https://dotnet.microsoft.com/download. A continuación, puede utilizar dotnet CLIpara crear un proyecto. Para este ejemplo, voy a utilizar .NET Core 3.1.

Vamos a crear un archivo llamado DynamicModelDemonuevo proyecto .NET Core Console:

dotnet new console --name DynamicModelDemo

A continuación, crear una nueva solución con la siguiente orden:

dotnet new sln --name DynamicModelDemo

A continuación, utilice el siguiente comando para agregar el elemento que acaba de crear en la solución:

dotnet sln add "DynamicModelDemo/DynamicModelDemo.csproj"

A continuación, puede abrir la solución con Visual Studio.

Crear un modelo

El modelo es muy simple. Añadir un proyecto llamado en el ConfigurableEntity.csnuevo archivo:

using System;

namespaceDynamicModelDemo
{
    publicclassConfigurableEntity
    {
        publicint Id { get; set; }
        publicstring Title { get; set; }
        publicstring Content { get; set; }
        public DateTime CreateDateTime { get; set; }
    }
}

Vamos a utilizar la CreateDateTimepropiedad para determinar qué modelo se debe asignar a las tablas.

Añadir ADO.NET Entity Framework Core

Vaya al directorio del proyecto y añadir los paquetes requeridos EF.Core con el siguiente comando:

dotnet add package Microsoft.EntityFrameworkCore.SqlSever
dotnet add package Microsoft.EntityFrameworkCore.Design

Si no ha instalado la herramienta EF, ejecute el siguiente comando para instalar:

dotnet tool install --global dotnet-ef

Esto le permite crear aplicaciones o migrar a actualizar la base de datos utilizando la herramienta de migración ef dotnet.

La creación de DbContext

Añadir a un proyecto llamado DynamicContext.csel nuevo archivo de clase. Se muestra de la siguiente manera:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using System;

namespaceDynamicModelDemo
{
    publicclassDynamicContext : DbContext
    {
        public DbSet<ConfigurableEntity> Entities { get; set; }

        #region OnConfiguring
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            => optionsBuilder
                .UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=DynamicContext;Trusted_Connection=True;");
        #endregion

        #region OnModelCreating
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<ConfigurableEntity>(b =>
            {
                b.HasKey(p => p.Id);
            });
        }
        #endregion
    }
}

En la actualidad, esto es sólo la configuración básica de EF.Core. Se utiliza la asignación predeterminada, lo que significa que el modelo se asigna al nombre Entitiesde la tabla. Por lo tanto, si queremos que en base a su CreateDateTimemapa del modelo a un diferentes propiedades de la tabla, cómo hacerlo?

Usted puede saber que podemos utilizar ToTable()para cambiar el nombre del método de la tabla, pero la manera de OnModelCreatingcambiar los nombres de las tablas de todos los modelos de acercarse a ella? Cuando el modelo EF, sólo una vez OnModelCreating. Así que de esta manera no se puede lograr.

En este caso, necesitamos IModelCacheKeyFactorycambiar la asignación predeterminada, a través del cual podemos personalizar el mecanismo de almacenamiento en caché de modelo para que EF puede crear diferentes modelos de acuerdo a sus atributos.

IModelCacheKeyFactory¿Qué es?

Esta es la documentación oficial de Microsoft explica:

EF utiliza  IModelCacheKeyFactory para generar claves de caché para los modelos.

Por defecto, EF se supone que para cualquier tipo dado de modelo de contexto es el mismo. Sin embargo, para nuestro programa, el modelo será diferente, ya que se asigna a una tabla diferente. Por lo tanto, tenemos que reemplazar nuestra implementación de IModelCacheKeyFactorylos servicios, la ejecución sería más clave de caché para mapear el modelo a la tabla correcta.

Tenga en cuenta que este procedimiento proporciona típicamente la interfaz y otra extendida por la base de datos, generalmente no se usa el código de aplicación. Sin embargo, para nuestro escenario, este es un enfoque viable.

realizaciónIModelCacheKeyFactory

Tenemos que CreateDateTimedistinguir entre las tablas. En DynamicContextla adición de una clase de propiedad:

public DateTime CreateDateTime { get; set; }

Añadir un proyecto llamado en el DynamicModelCacheKeyFactory.csnuevo archivo de clase. Código de la siguiente manera:

using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;

namespaceDynamicModelDemo
{
    publicclassDynamicModelCacheKeyFactory : IModelCacheKeyFactory
    {
        public object Create(DbContext context)
            => context is DynamicContext dynamicContext
                ? (context.GetType(), dynamicContext.CreateDateTime)
                : (object)context.GetType();
    }
}

Si bien la creación de un modelo clave de caché, esta aplicación será considerada CreateDateTimepropiedad.

solicitudIModelCacheKeyFactory

A continuación, se puede registrar un nuevo contexto IModelCacheKeyFactory:

#region OnConfiguring
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
            => optionsBuilder
                .UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=DynamicContext;Trusted_Connection=True;")
                .ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>();
#endregion

De manera que podamos en OnModelCreatingcada asignación de nombre de la tabla del método:

#region OnModelCreating
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
      modelBuilder.Entity<ConfigurableEntity>(b =>
            {
                b.ToTable(CreateDateTime.ToString("yyyyMMdd"));
                b.HasKey(p => p.Id);
            });
}
#endregion

CreateDateTimeA partir de DynamicContextla propiedad.

Podemos crear DynamicContextun tiempo especificado CreateDateTimeatributos:

var context = new DynamicContext { CreateDateTime = datetime };

Si datetimees 2020/03/27, entonces contextel modelo se asigna al nombre 20200327de la tabla.

Crear una base de datos

Antes código de verificación, que necesitamos para crear la base de datos. Sin embargo, la migración EF no es la mejor solución para esta situación, porque a medida que pasa el tiempo, el sistema generará más tablas. Nosotros sólo lo utilizan para crear un poco de muestra para verificar la tabla de asignación. De hecho, el sistema debe tener otro tablas generadas dinámicamente base diaria.

Ejecute el comando siguiente para crear la primera migración:

dotnet ef migrations add InitialCreate

Verá Migrationsgenera dos archivos de la carpeta. Abra el xxx_InitialCreate.csarchivo y actualizar Hasta método con el siguiente código:

protected override void Up(MigrationBuilder migrationBuilder)
{
      for (int i = 0; i < 30; i++)
      {
           var index = i;
           migrationBuilder.CreateTable(
               name: DateTime.Now.AddDays(-index).ToString("yyyyMMdd"),
               columns: table => new
               {
                    Id = table.Column<int>(nullable: false)
                            .Annotation("SqlServer:Identity", "1, 1"),
                    Title = table.Column<string>(nullable: true),
                    Content = table.Column<string>(nullable: true),
                    CreateDateTime = table.Column<DateTime>(nullable: false)
               },
               constraints: table =>
               {
                    table.PrimaryKey($"PK_{DateTime.Now.AddDays(-index):yyyyMMdd}", x => x.Id);
               });
        }
    }

Cambios es garantizar que la base de datos puede tener suficientes mesas para las pruebas. Tenga en cuenta que no debemos usar este enfoque en un entorno de producción .

A continuación, puede utilizar este comando para crear y actualizar la base de datos:

dotnet ef database update

Verá que genera los últimos 30 días de la tabla en la base de datos.

verificar Mapeo

Ahora comprobar el nuevo mapa. Al actualizar el código Program.csen Mainel método:

static void Main(string[] args)
{
    DateTime datetime1 = DateTime.Now;
    using (var context = new DynamicContext { CreateDateTime = datetime1 })
    {
        context.Entities.Add(new ConfigurableEntity { Title = "Great News One", Content = $"Hello World! I am the news of {datetime1}", CreateDateTime = datetime1 });
        context.SaveChanges();
    }
    DateTime datetime2 = DateTime.Now.AddDays(-1);
    using (var context = new DynamicContext { CreateDateTime = datetime2 })
    {
        context.Entities.Add(new ConfigurableEntity { Title = "Great News Two", Content = $"Hello World! I am the news of {datetime2}", CreateDateTime = datetime2 });
        context.SaveChanges();
    }

    using (var context = new DynamicContext { CreateDateTime = datetime1 })
    {
        var entity = context.Entities.Single();
          // Writes news of today
        Console.WriteLine($"{entity.Title} {entity.Content} {entity.CreateDateTime}");
    }

    using (var context = new DynamicContext { CreateDateTime = datetime2 })
    {
        var entity = context.Entities.Single();
        // Writes news of yesterday
        Console.WriteLine($"{entity.Title} {entity.Content} {entity.CreateDateTime}");
    }
}

Verá el siguiente resultado:

Ahora, podemos transferir CreateDateTimela propiedad de utilizar el mismo DbContextpara representar los diferentes modelos.

Publicado seis artículos originales · ganado elogios 19 · Vistas de 100.000 +

Supongo que te gusta

Origin blog.csdn.net/lixiaoer757/article/details/105303868
Recomendado
Clasificación