Я хотел сделать то же самое (добавить ленивую загрузку) по нескольким причинам, связанным с производительностью - я хотел избежать синхронизации запросов, потому что они блокируют поток, а в некоторых местах я хочу избежать загрузки полной сущности, а вместо этого просто загрузить свойства, которые нужны коду.
Просто отключить отложенную загрузку недостаточно, потому что некоторые объекты имеют свойства, которые на законных основаниях могут быть нулевыми, и я не хочу путать «нулевой, потому что он нулевой» с «нулевым, потому что мы решили не загружать его».
Я также хотел опционально добавлять ленивую загрузку в некоторые конкретные пути кода, где я знаю, что ленивая загрузка проблематична.
Ниже мое решение.
В моем классе DbContext добавьте это свойство:
class AnimalContext : DbContext
{
public bool ThrowOnSyncQuery { get; set; }
}
Где-нибудь при запуске моего кода, запустите это:
// Optionally don't let EF execute sync queries
DbInterception.Add(new ThrowOnSyncQueryInterceptor());
Код для ThrowOnSyncQueryInterceptor
выглядит следующим образом:
public class ThrowOnSyncQueryInterceptor : IDbCommandInterceptor
{
public void NonQueryExecuting(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
OptionallyThrowOnSyncQuery(interceptionContext);
}
public void NonQueryExecuted(DbCommand command, DbCommandInterceptionContext<int> interceptionContext)
{
}
public void ReaderExecuting(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
OptionallyThrowOnSyncQuery(interceptionContext);
}
public void ReaderExecuted(DbCommand command, DbCommandInterceptionContext<DbDataReader> interceptionContext)
{
}
public void ScalarExecuting(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
OptionallyThrowOnSyncQuery(interceptionContext);
}
public void ScalarExecuted(DbCommand command, DbCommandInterceptionContext<object> interceptionContext)
{
}
private void OptionallyThrowOnSyncQuery<T>(DbCommandInterceptionContext<T> interceptionContext)
{
// Short-cut return on async queries.
if (interceptionContext.IsAsync)
{
return;
}
// Throw if ThrowOnSyncQuery is enabled
AnimalContext context = interceptionContext.DbContexts.OfType<AnimalContext>().SingleOrDefault();
if (context != null && context.ThrowOnSyncQuery)
{
throw new InvalidOperationException("Sync query is disallowed in this context.");
}
}
}
Тогда в коде, который использует AnimalContext
using (AnimalContext context = new AnimalContext(_connectionString))
{
// Disable lazy loading and sync queries in this code path
context.ThrowOnSyncQuery = true;
// Async queries still work fine
var dogs = await context.Dogs.Where(d => d.Breed == "Corgi").ToListAsync();
// ... blah blah business logic ...
}