我渴望加载(通过使用.Include())相关实体,以便最大限度地减少为特定“大规模”数据网格生成的SQL查询的数量。在POCO中,相关实体是公共虚拟导航属性,这意味着它们是懒惰加载的。我想保留延迟加载这些相关实体的默认行为,因为它最适合我项目的其他部分。
现在,发生的事情是,在急切加载相关实体之后,我可以看到仍然生成了大量的查询。这是仅针对相关实体为空的查询(null因为sql加入“找到”没有相关数据)。
这使我相信EF会在稍后在表示层中访问它们时尝试延迟加载这些实体(认为它们尚未加载)。
我是否错过了一些基本的东西,或者有什么方法可以解决这个问题吗?
示例代码
使用存储库模式,这里有一些简化的方法(省略分页,排序,过滤等)。
通用存储库中的Get方法
public IEnumerable<T> Get(
Expression<Func<T, object>>[] includes = null)
{
IQueryable<T> query = set;
...
// Include properies for eager loading
if (includes != null)
{
query = includes.Aggregate(query,
(current, include) => current.Include(include));
}
...
return query.ToList();
}
上面是从服务类调用的,类似这样的
...
context.Licenses.Get(
includes: new Expression<Func<License, object>>[] { l => l.Comment }
);
...
许可证POCO
public class License
{
public License()
{
}
// Primitive properties
public string ID { get; set; }
public string Name { get; set; }
...
// Navigation properties
public virtual LicenseComment Comment { get; set; }
...
}
LicenseComment POCO
public class LicenseComment
{
public LicenseComment()
{
}
// Primitive properties
public string LicenseID { get; set; }
public string Comment { get; set; }
}
在MVC Razor视图中(或在模型中访问该属性)
<span>@license.Comment</span>
每当我尝试访问null(通过SQL Server Profiler查找)时,就会生成额外的SQL查询,这在我看来Entity Framework延迟加载,即使我急切地包含了这个属性。
答案 0 :(得分:2)
我无法尝试知道,但我希望不会发生这种情况。无论如何,如果你有一个页面,你不希望延迟加载发生,你只需关闭该页面:
context.Configuration.LazyLoadingEnabled = false;
或者您可以为这些查询关闭代理创建 - 未经过代理的实体无法使用延迟加载:
context.Configuration.ProxyCreationEnabled = false;
答案 1 :(得分:0)
我同意@Ladislav认为它不应该发生并测试“正常”行为如下:
如果您加载许可证,包括评论......
var license = context.Licenses.Include(l => l.Comment).Single(l => l.ID == 1);
... EF将导航属性标记为已加载:
var isCommentLoaded = context.Entry(license).Reference(l => l.Comment).IsLoaded;
无论评论是null
还是isCommentLoaded
都是true
,并且在您访问Comment
媒体资源时不会发出延迟加载查询。
即使您不使用预先加载......
var license = context.Licenses.Single(l => l.ID == 1);
... isCommentLoaded
将为true
,如果数据库中的注释许可证中的外键为NULL
(但它将为{{1}如果外键不是false
)。原因是EF总是将NULL
语句中的外键加载到上下文中,如果此键为SELECT
,EF知道数据库中没有相关注释,并将导航属性标记为已加载避免不必要的延迟加载。
答案 2 :(得分:0)
虽然不完全是你的情况,但我有类似的东西,并且我指出有一个额外的属性访问权限不属于原始包含。