I have an IQueryable extension method:
public static void SomeExt<T>(this IQueryable<T> query, DbContext context) {...}
and I would like to know if there is some way to get DbContext from query so that DbContext argument could be removed leaving only:
public static void SomeExt<T>(this IQueryable<T> query) {...}
I have tried something like this Access DataContext behind IQueryable but its not working, getting zero fields.
Also there is way to get it from DbSet
Can you get the DbContext from a DbSet?
myDbSet.GetService<'ICurrentDbContext>().Context;
but that's not what I need. I want to get it from Query?
This is the query:
var q = context.Items.Where(a => a.StatusId = 1);
q.SomeExt(context);
vs
q.SomeExt();
I have found a way to do this
public static DbContext GetDbContext(IQueryable query)
{
var bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
var queryCompiler = typeof(EntityQueryProvider).GetField("_queryCompiler", bindingFlags).GetValue(query.Provider);
var queryContextFactory = queryCompiler.GetType().GetField("_queryContextFactory", bindingFlags).GetValue(queryCompiler);
var dependencies = typeof(RelationalQueryContextFactory).GetProperty("Dependencies", bindingFlags).GetValue(queryContextFactory);
var queryContextDependencies = typeof(DbContext).Assembly.GetType(typeof(QueryContextDependencies).FullName);
var stateManagerProperty = queryContextDependencies.GetProperty("StateManager", bindingFlags | BindingFlags.Public).GetValue(dependencies);
var stateManager = (IStateManager)stateManagerProperty;
return stateManager.Context;
}
For EFCore 3 instead of
.GetProperty("Dependencies", bindingFlags)
use
.GetField("_dependencies", bindingFlags)
try this
public static DbContext GetDbContext(this IQueryable query)
{
var compilerField = typeof(EntityQueryProvider).GetField("_queryCompiler", BindingFlags.NonPublic | BindingFlags.Instance);
var compiler = (QueryCompiler)compilerField.GetValue(query.Provider);
var queryContextFactoryField = compiler.GetType().GetField("_queryContextFactory", BindingFlags.NonPublic | BindingFlags.Instance);
var queryContextFactory = (RelationalQueryContextFactory)queryContextFactoryField.GetValue(compiler);
object stateManagerDynamic;
var dependenciesProperty = typeof(RelationalQueryContextFactory).GetProperty("Dependencies", BindingFlags.NonPublic | BindingFlags.Instance);
if (dependenciesProperty != null)
{
// EFCore 2.x
var dependencies = dependenciesProperty.GetValue(queryContextFactory);
var stateManagerField = typeof(DbContext).GetTypeFromAssembly_Core("Microsoft.EntityFrameworkCore.Query.QueryContextDependencies").GetProperty("StateManager", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
stateManagerDynamic = stateManagerField.GetValue(dependencies);
}
else
{
// EFCore 1.x
var stateManagerField = typeof(QueryContextFactory).GetProperty("StateManager", BindingFlags.NonPublic | BindingFlags.Instance);
stateManagerDynamic = stateManagerField.GetValue(queryContextFactory);
}
IStateManager stateManager = stateManagerDynamic as IStateManager;
if (stateManager == null)
{
Microsoft.EntityFrameworkCore.Internal.LazyRef<IStateManager> lazyStateManager = stateManagerDynamic as Microsoft.EntityFrameworkCore.Internal.LazyRef<IStateManager>;
if (lazyStateManager != null)
{
stateManager = lazyStateManager.Value;
}
}
if (stateManager == null)
{
stateManager = ((dynamic)stateManagerDynamic).Value;
}
return stateManager.Context;
}