Ok, so looking at source code for the CompiledQuery
which gets returned from CompiledQuery.Compile()
we can verify that the query is only actually compiled once you invoke the method for the first time:
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;
}
So there is no way to force the compilation without actually executing it.
However, I did find a hacky workaround for it which gives me what I need. There is a way we can execute the query thus causing the query to be precompiled without allowing the call to the database:
// 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);
}