我知道这里讨论的方法:
Solving common problems with Compiled Queries in Linq to Sql for high demand ASP.NET websites
...但这对我的情况不起作用,因为我得到了:
“从查询返回结果后,不允许设置加载选项。”
我使用Codesmith PLINQO脚本生成实体和管理器代码,管理器代码如下所示:
public partial class SearchManager
{
#region Query
// A private class for lazy loading static compiled queries.
private static partial class Query
{
internal static readonly Func<MyDataContext,IOrderedQueryable<Search>>
GetAll = CompiledQuery.Compile(
(MyDataContext db) =>
from s in db.Search
orderby s.Name
select s);
}
#endregion
public IQueryable<Search> GetAll()
{
return Query.GetAll(Context);
}
}
我首先尝试将静态DataLoadOptions拖放到Searchmanager类中,如下所示:
public static readonly DataLoadOptions MyOptions =
(new Func<DataLoadOptions>(() =>
{
var option = new DataLoadOptions();
option.LoadWith<Search>(x => x.Rule);
return option;
}))();
...然后将其提供给GetAll方法中的Context,如:
public IQueryable<Search> GetAll()
{
Context.LoadOptions = MyOptions;
return Query.GetAll(Context);
}
......这给了我上面提到的错误。这是因为查询已经编译,因此不能添加“额外”DataLoadOptions吗?如果是这样,如何在编译查询之前应用DataLoadOptions?
答案 0 :(得分:2)
在DataContext类的setter属性中,有一个条件检查DataContext是否在其Cache中有任何对象,并且LoadOptions是非null,并且您尝试设置的LoadOptions实例与一个已经设置,然后你得到那个例外。
备选方案#1。为每个查询创建一个新的上下文(可能不是一个好主意)
备选方案#2。使用反射调用ClearCache方法,然后静态创建一个新的LoadOptions,将其分配给Context,最后获取编译的查询。
public partial class SearchManager
{
#region Query
// A private class for lazy loading static compiled queries.
private static partial class Query
{
internal static readonly Func<MyDataContext,IOrderedQueryable<Search>> GetAll
{
get {
return CompiledQuery.Compile(
(MyDataContext db) =>
from s in db.Search
orderby s.Name
select s);
}
}
#endregion
public IQueryable<Search> GetAll()
{
Context.ClearCache();
Context.LoadOptions = MyOptions;
return Query.GetAll(Context);
}
public static readonly DataLoadOptions MyOptions =
(new Func<DataLoadOptions>(() => MakeLoadOptions<Search>(x=>x.Rule)))();
}
public static class Extensions {
public static void ClearCache(this DataContext context)
{
const BindingFlags FLAGS = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
var method = context.GetType().GetMethod("ClearCache", FLAGS);
method.Invoke(context, null);
}
public static DataLoadOptions MakeLoadOptions<TEntity, TResult>(this Expression<Func<TEntity,TResult>> func) {
DataLoadOptions options = new DataLoadOptions();
options.LoadWith(func);
return options;
}
}
答案 1 :(得分:0)
错误消息本身会告诉您究竟出了什么问题。 Linq查询返回结果后,您无法应用DataLoadOptions。或者,也许更好的方式来说明如下。如果要应用DataLoadOptions,请在执行查询之前执行此操作。之后你不能这样做。
答案 2 :(得分:0)
您只能为已编译的查询设置一次加载选项。必须在第二次调用时抛出错误。将赋值移动到静态构造函数,这应该可以解决您的问题。
答案 3 :(得分:0)
public IQueryable<Search> GetAll() {
Context.LoadOptions = MyOptions;
return Query.GetAll(Context);
}
如果Context已经返回任何查询结果,则此分配为时已晚。这与编译的查询无关,也与分配DataContext的LoadOptions属性有关。不幸的是,msdn没有记录LoadOptions属性的这种行为。