我试图编写一个在执行前实例化DbContext
的查询提供程序,执行查询然后立即处理生成的上下文对象。
为此,我必须实施IQueryProvider.Execute(....)
。在此方法内部,我需要从IQueryProvider
对象获取DbContext
以使其执行查询。
问题是我不知道如何从上下文对象访问提供程序。据我所见,它存储在((IObjectContextAdapter)context).ObjectContext.QueryProvider
中,但该属性是内部的。
我也试过从DbSet中获取它,但我不知道要指定的类型。
context.Set(type?).AsQueryable().Provider.Execute<TResult>(expression)
或
context.Set<type?>().AsQueryable().Provider.Execute<TResult>(expression)
所以我的问题是如何从给定的IQueryProvider
对象中获取基础DbContext
。
我想针对同一个数据库在不同的上下文中执行多个查询。但是DbContext是IDisposable,你必须将它包装在using.Blocks中。
IEnumerable<T1> result1;
IEnumerable<T2> result2;
using(var context1 = new MyContext())
using(var context2 = new MyContext())
{
var result1Task = context1.Set<T1>().ToListAsync();
var result2Task = context2.Set<T2>().ToListAsync();
await Task.WhenAll(result1Task, result2Task).ConfigureAwait(false);
result1 = result1Task.Result;
result2 = result1Task.Result;
}
另一种方法是将其包装在自己的方法中:
// could also be written as generic method GetResultAsync<T>(),
// but you should get the point :)
async Task<IEnumerable<T1>> GetResult1Async()
{
using(var context = new MyContext())
return await context.Set<T1>().ToListAsync().ConfigureAwait(false);
}
async Task<IEnumerable<T2>> GetResult2Async()
{
using(var context = new MyContext())
return await context.Set<T2>().ToListAsync().ConfigureAwait(false);
}
var result1Task = GetResult1Async();
var result2Task = GetResult2Async();
await Task.WhenAll(result1Task, result2Task).ConfigureAwait(false);
var result1 = result1Task.Result;
var result2 = result1Task.Result;
两者都有很多样板代码,所以我想编写一个用于打开/处理上下文对象的概括。
我想简化这个:
var result1Task = repository.Set<T1>().ToListAsync();
var result2Task = repository.Set<T2>().ToListAsync();
await Task.WhenAll(result1Task, result2Task).ConfigureAwait(false);
var result1 = result1Task.Result;
var result2 = result1Task.Result;
诀窍是我希望repository.Set<T>()
返回IQueryable<T>
所以我可以使用所有Linq方法。为此,我试图创建我自己的IQueryProvider
,它在其Execute方法中使用-block包装上下文。
到目前为止,这是我的班级:
public class RepositoryQueryProvider<TContext> : IQueryProvider
where TContext : DbContext, new()
{
// some irrelevant code here
public TResult Execute<TResult>(Expression expression)
{
using (var context = new TContext())
{
var efProvider = ?; // how to get the provider from the context?
return efProvider.Execute<TResult>(expression);
}
}
}
答案 0 :(得分:0)
这很简单:
dbcontext.GetService<IAsyncQueryProvider>();
我认为不需要使用'使用'来对付DbContext