7

我最近切换到 Entity Framework 5。现在,我想从现有数据库生成 POCO 类,并且我需要延迟加载和更改跟踪。所以所有的标量属性都应该是虚拟的以及导航属性。

添加新的 ADO.Net 实体数据模型以 .edmx 文件和其他一些 .cs 和 .tt 文件结尾。

首先,我想知道为什么默认生成的 POCO 类不满足更改跟踪代理的要求,即标量属性不是虚拟的。

其次,如何生成启用代理的 poco 类?

PS:我接受了 Slauma 的答案作为迄今为止最好和唯一的答案,但我不同意它的第一部分。这是我的论点

Slauma 谈到了代理的两个问题:限制和性能:

  • 关于启用代理的实体的限制:当实体框架在 DB First 方法中生成类时,类必须遵循以启用更改跟踪代理的规则并不那么重要,因为它们根本没有限制性。谁真正关心导航集合是 IList 还是 HashSet?仅当应用程序中有设计好的类并且要从中生成表时,才有意义谈论这些限制。

  • DB 首先不支持复杂属性。所以我们可以将它们排除在我们的讨论之外。

  • 关于性能:在所讨论的文章中以及到目前为止我研究过的一些其他实验,结果并不是很有说服力地拒绝代理以支持快照。首先,实验是在大量实体(即 10,000 个)上进行的。您的应用程序(而不是数据库)中的批处理处理大量实体并非不可能,但是假设有更好的方法,例如存储过程。其次,根据应用程序的类型和需求,我们通常处理的实体数量很少,例如在实现和使用存储库模式时;代理和快照的性能没有区别。有趣的是,在所讨论的实验中,将相同的值重新分配给属性是代理性能显着失败的唯一情况。但真正做到这一点的是谁?很容易小心避免重复通知更改跟踪器。同样,在这种情况下,当处理大量实体时会出现重大问题。

4

1 回答 1

4

首先,我想知道为什么默认生成的 POCO 类不满足更改跟踪代理的要求,即标量属性不是虚拟的。

不建议使用更改跟踪代理作为默认更改跟踪策略。在这篇博文中有更详细的解释。本质上,使用变更跟踪代理的主要原因——与基于快照的变更跟踪相比性能更好——并不总是得到保证——有时甚至更糟——而且缺点列表比基于快照的变更跟踪要长。

过去,生成 POCO 实体的 T4 模板确实将所有属性(包括标量属性)标记为virtual并为基于代理的更改跟踪准备实体。由于博客中描述的原因,这已针​​对较新的模板进行了更改,包括 EF 5 的 DbContext 生成器,如上面链接的博客文章下方的评论中所述。现在,只有导航属性被标记为virtual,而不是标量属性,这允许延迟加载,但不足以用于更改跟踪代理。

其次,如何生成启用代理的 poco 类?

我不知道有任何可用的 T4 模板可以做到这一点,但是很容易修改默认模板以将标量属性也标记为virtual

  • 在您的项目中,您应该有两个带有.tt扩展名的文件:YourModelContainer.ttYourModelContainer.Context.tt. 打开YourModelContainer.tt文件。

  • 在此文件中,您将找到一个名为的方法Property

    public string Property(EdmProperty edmProperty)
    {
        return string.Format(
            CultureInfo.InvariantCulture,
            "{0} {1} {2} {{ {3}get; {4}set; }}",
            Accessibility.ForProperty(edmProperty),
            _typeMapper.GetTypeName(edmProperty.TypeUsage),
            _code.Escape(edmProperty),
            _code.SpaceAfter(Accessibility.ForGetter(edmProperty)),
            _code.SpaceAfter(Accessibility.ForSetter(edmProperty)));
    }
    

    换行...

            Accessibility.ForProperty(edmProperty),
    

    ...至...

            AccessibilityAndVirtual(Accessibility.ForProperty(edmProperty)),
    

而已。

顺便提一下,如果您不熟悉它,但还有第二种可用的 Database-First 方法,即将现有数据库反向工程为 Code-First 模型。这种方法根本不使用 T4 模板,而是使用 Fluent API 映射创建 Code-First 模型和上下文。如果您想自定义和扩展模型类(您也可以virtual手动添加修饰符)并在未来继续使用 Code-First 工作流程(和 Code-First 迁移)以更新和发展您的数据库模式,这将非常有用。

于 2013-08-25T14:59:30.953 回答