c# - Acceder dinĂ¡micamente a la tabla en EF Core 2.0
linq asp.net-core (2)
Estoy usando
System.Linq.Dynamic.Core
para agregar dinámicamente expresiones lambda a consultas en EF.
También quiero poder seleccionar la tabla por nombre. Encontré esta respuesta:
https://stackoverflow.com/a/28101268/657477
Pero no funciona en asp.net core 2.0.
No puedo usar
DbSet
. Debo usar
DbSet<TEntity>
que dice en el mensaje de error.
Quiero poder hacer
db.GetTable("Namespace.MyTable").Where(...)
¿Cómo puedo hacer esto?
EF Core ya no tiene un método .set no genérico, pero esta clase de extensión facilita la consulta de su tabla basada en una cadena usando linq dinámico
public static class DbContextExtensions
{
public static IQueryable<Object> Set(this DbContext _context, Type t)
{
return (IQueryable<Object>)_context.GetType().GetMethod("Set").MakeGenericMethod(t).Invoke(_context, null);
}
public static IQueryable<Object> Set(this DbContext _context, String table)
{
Type TableType = _context.GetType().Assembly.GetExportedTypes().FirstOrDefault(t => t.Name == table);
IQueryable<Object> ObjectContext = _context.Set(TableTypeDictionary[table]);
return ObjectContext;
}
}
}
uso:
IQueryable<Object> query = db.Set("TableName");
// Filter against "query" variable below...
List<Object> result = query.ToList();
// or use further dynamic Linq
IQueryable<Object> query = db.Set("TableName").Where("t => t.TableFilter == /"MyFilter/"");
Primero debe obtener el tipo de entidad del nombre (en caso de que tenga el tipo, simplemente utilícelo directamente).
Puede usar la reflexión para eso, pero probablemente la forma correcta de EF Core es usar el método
FindEntityType
.
Una vez que tenga el tipo, el problema es cómo obtener el
DbSet<T>
.
EF Core actualmente no proporciona un método
Set(Type)
no genérico similar a EF6, principalmente porque no hay
DbSet
clase
DbSet
no genérica.
Pero aún puede obtener el
DbSet<T>
correspondiente como
DbSet<T>
utilizando algunos elementos internos de EF Core:
using System;
using System.Linq;
using Microsoft.EntityFrameworkCore.Internal;
namespace Microsoft.EntityFrameworkCore
{
public static partial class CustomExtensions
{
public static IQueryable Query(this DbContext context, string entityName) =>
context.Query(context.Model.FindEntityType(entityName).ClrType);
public static IQueryable Query(this DbContext context, Type entityType) =>
(IQueryable)((IDbSetCache)context).GetOrAddSet(context.GetDependencies().SetSource, entityType);
}
}
o invocando el método genérico
Set<T>
través de la reflexión:
using System;
using System.Linq;
using System.Reflection;
namespace Microsoft.EntityFrameworkCore
{
public static partial class CustomExtensions
{
public static IQueryable Query(this DbContext context, string entityName) =>
context.Query(context.Model.FindEntityType(entityName).ClrType);
static readonly MethodInfo SetMethod = typeof(DbContext).GetMethod(nameof(DbContext.Set));
public static IQueryable Query(this DbContext context, Type entityType) =>
(IQueryable)SetMethod.MakeGenericMethod(entityType).Invoke(context, null);
}
}
En ambos casos puedes usar algo como esto:
db.Query("Namespace.MyTable").Where(...)
o
db.Query(typeof(MyTable)).Where(...)