0

我正在使用 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 子句, ETC)。

4

2 回答 2

1

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

于 2013-03-12T13:21:34.737 回答
0

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

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

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

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

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

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

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

于 2013-03-12T14:14:06.420 回答