c# linq asp.net-core entity-framework-core

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(...)