web-dev-qa-db-fra.com

Accéder dynamiquement à la table dans EF Core 2.0

J'utilise System.Linq.Dynamic.Core Pour ajouter dynamiquement des expressions lambda aux requêtes dans EF.

Je souhaite également pouvoir sélectionner le tableau par son nom. J'ai trouvé cette réponse:

https://stackoverflow.com/a/28101268/657477

Mais cela ne fonctionne pas dans asp.net core 2.0. Je ne peux pas utiliser DbSet Je dois utiliser DbSet<TEntity> Comme indiqué dans le message d'erreur.

Je veux pouvoir faire db.GetTable("Namespace.MyTable").Where(...)

Comment puis-je faire ceci?

11
Guerrilla

Vous devez d'abord obtenir le type de l'entité à partir du nom (au cas où vous auriez le type, utilisez-le directement). Vous pouvez utiliser la réflexion pour cela, mais probablement la bonne façon pour EF Core est d'utiliser la méthode FindEntityType .

Une fois que vous avez le type, le problème est de savoir comment obtenir le DbSet<T> Correspondant. EF Core ne fournit actuellement pas de méthode Set(Type) non générique similaire à EF6, principalement parce qu'il n'y a pas de classe DbSet non générique. Mais vous pouvez toujours obtenir le DbSet<T> Correspondant en tant que IQueryable en utilisant des internes 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);
    }
}

ou en invoquant la méthode générique Set<T> via la réflexion:

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);
    }
}

Dans les deux cas, vous pouvez utiliser quelque chose comme ceci:

db.Query("Namespace.MyTable").Where(...)

ou

db.Query(typeof(MyTable)).Where(...)
20
Ivan Stoev

EF Core n'a plus de méthode .set non générique, mais cette classe d'extension facilite l'interrogation de votre table en fonction d'une chaîne à l'aide de linq dynamique

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;
    }
}

}

usage:

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\"");
4
jdmneon