Jam*_*ing 6 entity-framework lazy-loading eager-loading entity-framework-4
我们有一些应用程序当前正在使用启用了延迟加载的 EF 模型。当我关闭延迟加载(以避免隐式加载和我们的大多数 N+1 选择)时,我宁愿访问应该已经热切加载(或在引用上手动 Load() )抛出异常而不是返回 null(因为特定的异常比 null 引用更好、更容易调试)。
我目前倾向于仅修改 t4 模板来执行此操作(因此,如果 reference.IsLoaded == false,则抛出),但想知道这是否已经是一个已解决的问题,无论是在框中还是通过另一个项目。
任何对可以进行源分析并检测此类问题的插件/扩展/等的引用的奖励积分。:)
出于几个与性能相关的原因,我想做同样的事情(引发延迟加载) - 我想避免同步查询,因为它们会阻塞线程,并且在某些地方我想避免加载完整的实体,而只是加载属性代码需要的。
仅禁用延迟加载还不够好,因为某些实体具有可以合法为 null 的属性,并且我不想将“null 因为它是 null”与“null 因为我们决定不加载它”混淆。
我还只想选择性地在某些特定的代码路径中启用延迟加载,我知道延迟加载是有问题的。
以下是我的解决方案。
在我的 DbContext 类中,添加此属性:
class AnimalContext : DbContext
{
public bool ThrowOnSyncQuery { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在我的代码启动的某个位置,运行以下命令:
// Optionally don't let EF execute sync queries
DbInterception.Add(new ThrowOnSyncQueryInterceptor());
Run Code Online (Sandbox Code Playgroud)
其代码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.");
}
}
}
Run Code Online (Sandbox Code Playgroud)
然后在使用的代码中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 ...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
670 次 |
| 最近记录: |