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 CLI
para crear un proyecto. Para este ejemplo, voy a utilizar .NET Core 3.1.
Vamos a crear un archivo llamado DynamicModelDemo
nuevo 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.cs
nuevo 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 CreateDateTime
propiedad 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.cs
el 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 Entities
de la tabla. Por lo tanto, si queremos que en base a su CreateDateTime
mapa 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 OnModelCreating
cambiar 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 IModelCacheKeyFactory
cambiar 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 IModelCacheKeyFactory
los 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 CreateDateTime
distinguir entre las tablas. En DynamicContext
la adición de una clase de propiedad:
public DateTime CreateDateTime { get; set; }
Añadir un proyecto llamado en el DynamicModelCacheKeyFactory.cs
nuevo 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 CreateDateTime
propiedad.
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 OnModelCreating
cada 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
CreateDateTime
A partir de DynamicContext
la propiedad.
Podemos crear DynamicContext
un tiempo especificado CreateDateTime
atributos:
var context = new DynamicContext { CreateDateTime = datetime };
Si datetime
es 2020/03/27
, entonces context
el modelo se asigna al nombre 20200327
de 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á Migrations
genera dos archivos de la carpeta. Abra el xxx_InitialCreate.cs
archivo 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.cs
en Main
el 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 CreateDateTime
la propiedad de utilizar el mismo DbContext
para representar los diferentes modelos.