Как я могу "разогреть" предварительно скомпилированный запрос LinqToSql?
В LinqToSql предварительно скомпилированные запросы - это хорошо, но мне все равно нужно, чтобы я испытал производительность компиляции при первом использовании запроса.
Я хотел бы "разогреть" эти предварительно скомпилированные запросы в фоновом режиме при запуске приложения. Очевидно, что я могу сделать это, вызывая их с некоторыми параметрами по умолчанию - однако это приводит к ненужному попаданию в базу данных.
Есть ли способ "разогреть" предварительно скомпилированный запрос, не обращаясь к базе данных?
Я взглянул на исходный код CompliedQuery, но кажется, что многие из необходимых классов запечатаны и / или внутренние...
1 ответ
Итак, глядя на исходный код для 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;
}
Таким образом, нет способа форсировать компиляцию без ее фактического выполнения.
Тем не менее, я нашел хакерский обходной путь, который дает мне то, что мне нужно. Есть способ, которым мы можем выполнить запрос, таким образом вызывая его предварительную компиляцию, не допуская обращения к базе данных:
// 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);
}