【问题标题】: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 子句等)。

【问题讨论】:

    标签: .net linq orm telerik telerik-open-access


    【解决方案1】:

    我不能肯定地说 Telerik 工具,但我怀疑它们有点类似于 EF 和 LINQ to SQL,它们在调用 GetEnumerator(由 ToList 内部调用)时评估任何表达式。要自己进行测试,请使用分析工具来准确识别数据库请求的发出位置。 SQL Profiler 和 Intellitrace 应该适用于分析。还有其他可用的商业分析器,但我不确定 Telerik Open Access 有什么。您可能想查看他们的论坛。

    【讨论】:

      【解决方案2】:

      我不了解 OpenAccess,但我认为大致相同的原则适用于实体框架。从那个背景来看,我只看到您的代码存在重大问题。

      第一个反对意见是从架构的角度来看的。您的实体对象不应该知道上下文的存在。

      其他反对意见是技术性的。

      • 正如您已经指出的,您的代码将在每次处理 SystemUsers 时执行。 ToList() 总是会导致数据库命中。我不确定如果删除ToList() 会发生什么,这取决于GetChangesGetDeletes 的作用。我不知道。但至少每次枚举SystemUsers 时都会导致额外的数据库命中。

      • 我假设,像 EF 一样,OpenAccess 也支持延迟加载标记为 virtual 的集合。可能它创建了一个从实体类型派生的代理类型,并为导航属性添加了连接以实现延迟加载。由于该属性只有一个吸气剂,我假设 OpenAccess 通过 Adding 向它填充一个集合。这会导致各种副作用:

        1. 这意味着每次添加项目时都会访问(运行查询)基本属性。
        2. 您的代码返回一个临时列表。下次您处理该物业时,任何添加的项目都将消失!!集合永远不会被填充。
      • 最后,当您的对象正在物化时打开第二个阅读器时,它可能会导致不可预知的行为。

      所以我认为您应该通过一个存储库来解决软删除问题,该存储库返回带有或不带有标记为删除的实体的实体。或者,也许您可​​以创建一个计算的(未映射的)属性,该属性返回没有“已删除”的 SystemUsers。

      【讨论】:

      • 你提出了一些好观点。我想我会停止走这条危险的道路。
      猜你喜欢
      • 2018-11-11
      • 2021-12-30
      • 1970-01-01
      • 2018-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-08
      • 1970-01-01
      相关资源
      最近更新 更多