web-dev-qa-db-ja.com

EF Core 2.0のテーブルに動的にアクセスする

_System.Linq.Dynamic.Core_を使用して、EFのクエリにラムダ式を動的に追加しています。

また、名前でテーブルを選択できるようにしたいです。私はこの答えを見つけました:

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

ただし、asp.net core 2.0では機能しません。 DbSetは使用できません。エラーメッセージに記載されている_DbSet<TEntity>_を使用する必要があります。

db.GetTable("Namespace.MyTable").Where(...)ができるようにしたい

これどうやってするの?

11
Guerrilla

最初に、名前からエンティティのタイプを取得する必要があります(タイプがある場合は、それを直接使用します)。そのためにリフレクションを使用できますが、おそらくEF Coreの正しい方法は FindEntityType メソッドを使用することです。

型を取得したら、対応する_DbSet<T>_を取得する方法が問題になります。現在、EF CoreはEF6に似た非ジェネリックSet(Type)メソッドを提供していません。これは主に非ジェネリックDbSetクラスがないためです。ただし、EF Core内部を使用することで、対応する_DbSet<T>_をIQueryableとして取得できます。

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

または、リフレクションを介して一般的な_Set<T>_メソッドを呼び出す:

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

どちらの場合でも、次のようなものを使用できます。

_db.Query("Namespace.MyTable").Where(...)
_

または

_db.Query(typeof(MyTable)).Where(...)
_
20
Ivan Stoev

EF Coreには一般的な非.setメソッドはありませんが、この拡張クラスを使用すると、動的linqを使用して文字列に基づいてテーブルを簡単に照会できます

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

}

使用法:

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