IList 在啥时候导致查询在 ORM 中执行?
Posted
技术标签:
【中文标题】IList 在啥时候导致查询在 ORM 中执行?【英文标题】:At what point does an IList cause a query to execute in an ORM?IList 在什么时候导致查询在 ORM 中执行? 【发布时间】:2013-03-12 12:04:53 【问题描述】:我正在使用 Telerik 的 OpenAccess ORM,并且正在对生成的代码进行一些更改。对于具有导航属性(另一个表的键)的实体,这些属性会生成为 IList,如下所示:
private IList<SystemUser> _SystemUsers = new List<SystemUser>();
public virtual IList<SystemUser> SystemUsers
get
return this._SystemUsers;
首先,SystemUsers
是在什么时候实际查询数据库的?它是一个 IList,所以我原以为这会在创建对象时针对数据库执行,但我知道事实并非如此。
我想要做的是过滤掉我所有生成的导航属性上的已删除项目,并且我一直在对 t4 模板进行更改以使用以下代码执行此操作:
private IList<SystemUser> _SystemUsers = new List<SystemUser>();
public virtual IList<SystemUser> SystemUsers
get
if (!Entities.IncludeDeletedEntities)
var currentContext = Entities.GetContext(this);
ContextChanges changes = currentContext.GetChanges();
IList<SystemUser> deletedItems = changes.GetDeletes<SystemUser>();
return this._SystemUsers.Except(deletedItems).ToList(); //Question is here
return this._SystemUsers;
本质上,这只是返回集合减去标记为删除的集合。我关心的是.ToList()
及其执行时间。我不想让ToList()
每次访问SystemUsers
时都查询数据库来减慢我的查询速度,但我也想过滤我的项目。我什至不确定ToList()
是否会导致数据库命中。我不确定代码何时会真正命中数据库,因此我正在寻找一些帮助/提示来过滤掉我已删除的项目而不使其命中数据库,直到我在代码中使用 SystemUsers
通过添加更多过滤器( where 子句等)。
【问题讨论】:
【参考方案1】:我不能肯定地说 Telerik 工具,但我怀疑它们有点类似于 EF 和 LINQ to SQL,它们在调用 GetEnumerator(由 ToList 内部调用)时评估任何表达式。要自己进行测试,请使用分析工具来准确识别数据库请求的发出位置。 SQL Profiler 和 Intellitrace 应该适用于分析。还有其他可用的商业分析器,但我不确定 Telerik Open Access 有什么。您可能想查看他们的论坛。
【讨论】:
【参考方案2】:我不了解 OpenAccess,但我认为大致相同的原则适用于实体框架。从那个背景来看,我只看到您的代码存在重大问题。
第一个反对意见是从架构的角度来看的。您的实体对象不应该知道上下文的存在。
其他反对意见是技术性的。
正如您已经指出的,您的代码将在每次处理 SystemUsers
时执行。 ToList()
总是会导致数据库命中。我不确定如果删除ToList()
会发生什么,这取决于GetChanges
和GetDeletes
的作用。我不知道。但至少每次枚举SystemUsers
时都会导致额外的数据库命中。
我假设,像 EF 一样,OpenAccess 也支持延迟加载标记为 virtual
的集合。可能它创建了一个从实体类型派生的代理类型,并为导航属性添加了连接以实现延迟加载。由于该属性只有一个吸气剂,我假设 OpenAccess 通过 Add
ing 向它填充一个集合。这会导致各种副作用:
-
这意味着每次添加项目时都会访问(运行查询)基本属性。
您的代码返回一个临时列表。下次您处理该物业时,任何添加的项目都将消失!!集合永远不会被填充。
最后,当您的对象正在物化时打开第二个阅读器时,它可能会导致不可预知的行为。
所以我认为您应该通过一个存储库来解决软删除问题,该存储库返回带有或不带有标记为删除的实体的实体。或者,也许您可以创建一个计算的(未映射的)属性,该属性返回没有“已删除”的 SystemUsers。
【讨论】:
你提出了一些好观点。我想我会停止走这条危险的道路。以上是关于IList 在啥时候导致查询在 ORM 中执行?的主要内容,如果未能解决你的问题,请参考以下文章