在LinqToSql中,预编译的查询很棒 - 但它仍然需要我在第一次使用查询时获取编译性能。
我希望在应用程序启动时在后台“预热”这些预编译的查询。显然,我可以通过使用一些默认参数调用它们来做到这一点 - 但是这会导致对数据库的不必要的打击。
有没有办法在没有调用数据库的情况下“预热”预编译查询?
我已经看过CompliedQuery源代码,但似乎所需的许多类都是密封的和/或内部的......
答案 0 :(得分:0)
好的,所以查看从CompiledQuery
返回的CompiledQuery.Compile()
的源代码,我们可以验证只有在您第一次调用该方法时才实际编译该查询:
ICompiledQuery compiled;
private object ExecuteQuery(DataContext context, object[] args) {
if (context == null) {
throw Error.ArgumentNull("context");
}
if (this.compiled == null) {
lock (this) {
if (this.compiled == null) {
// This is where the query is copmiled
this.compiled = context.Provider.Compile(this.query);
this.mappingSource = context.Mapping.MappingSource;
}
}
}
// this is where the query is executed against the data store
return this.compiled.Execute(context.Provider, args).ReturnValue;
}
因此没有办法强制编译而不实际执行它。
然而,我确实找到了一个hacky解决方法,它给了我我需要的东西。有一种方法可以执行查询,从而导致查询被预编译而不允许调用数据库:
// compiled query
static Func<NorthwindDataContext, int, IQueryable<Order>> GetOrderById =
CompiledQuery.Compile((NorthwindDataContext db, int orderId) => LINQ GOES HERE );
static void Warmup()
{
var context = new NorthwindDataContext("ConnectionString");
// dispose the connection to force the attempted database call to fail
context.Connecction.Dispose();
try
{
GetOrderById(context, 1);
}
catch (Exception ex)
{
// we expect to find InvalidOperationException with the message
// "The ConnectionString property has not been initialized."
// but the underlying query will now be compiled
}
}
static void GetData()
{
// as long as we called warmup first, this will not take the compilation performance hit
var context = new NorthwindDataContext("ConnectionString");
var result = GetOrderById(context, 1);
}