首先关闭EF代码的CTP5 ProxyCreationEnabled的不利之处是什么


82

我的WCF服务可以从代码的第一个模型回归类的唯一方法是通过设置ProxyCreationEnablefalse使用下面的代码。

((IObjectContextAdapter)MyDb).ObjectContext.ContextOptions.ProxyCreationEnable = false;

这样做的负面后果是什么?一个好处是,我至少可以将这些动态类型序列化,以便可以使用WCF通过电线发送它们。

Answers:


71

动态代理用于更改跟踪和延迟加载。当WCF尝试序列化对象时,通常会关闭并处置相关的上下文,但是导航属性的序列化将自动触发延迟加载(在封闭的上下文上)=>异常。

如果您关闭延迟加载,则需要对所有要使用的导航属性使用快速加载(在ObjectQuery上包含)。跟踪更改不适用于WCF,它仅适用于修改附加到ObjectContext的实体。


7
禁用ProxyCreationEnabled对性能有好处吗?例如,我经常抓取一个DbContext实例只是为了进行急于加载的读取。
克里斯·莫斯基尼

2
@ChrisMoschini“当POCO实体没有更改跟踪代理时,通过将您的实体的内容与先前保存状态的副本进行比较来发现更改。当您的上下文中有许多实体时,这种深度比较将成为一个漫长的过程,或者当您的实体具有大量属性时,即使自上次比较以来它们都没有变化。” msdn.microsoft.com/en-us/library/hh949853(v=vs.113).aspx
Niklas Peter

75

如果DbContext.Configuration.ProxyCreationEnabled设置为false,除非Include在父对象上调用方法,否则DbContext将不会为某些父对象加载子对象。设置DbContext.Configuration.LazyLoadingEnabledtruefalse不会对其行为产生影响。

如果DbContext.Configuration.ProxyCreationEnabled设置为true,则将自动加载子对象,DbContext.Configuration.LazyLoadingEnabled值将控制何时加载子对象。


10

使用EF时,默认情况下它将为您的班级创建一个代理。解决方案可以是在DbContext类的构造函数中添加此行。您的数据模型继承自DbContext类,因此您可以像这样编辑模型:

    public yourDataModelEntities()
        : base("name=yourDataModelEntities")
    {
        base.Configuration.ProxyCreationEnabled = false;
    }

这个类是在你EF.edmx然后在yourmodel.Context.tt随后yourmodel.Context.cs


2
这不是答案,但无论如何对我有帮助。
山本彰(Akira Yamamoto)

1
您对如何自动执行该生产线有很好的建议吗?每次我重新创建模型时,我肯定会忘记将属性设置为false,这可能需要花费数小时的调试时间,才能有人意识到它的问题所在。
Konrad Viltersten 2015年

@konrad-在局部类中创建代码,这样就不会被覆盖。 公共部分类yourDataMoldelEntities()
Mikee

@Mikee真的吗?由于自动生成的构造函数与我在局部类中编写的构造函数发生冲突,因此我可能会遇到一些问题……
Konrad Viltersten

@konrad他们创造了局部类“类型”,给你一个京顺路没有你的代码覆盖
Mikee

6

(使用Visual Studio 2013或更高版本)

为避免每次从数据库中刷新模型时,都避免在EF模型中编辑类构造函数,或以其他方式触发代码的重建,进行更改的适当位置是在负责该更改的T4代码文件中实际创建模型代码。几年前,当我了解有关如何实际创建类和属性的基本机制时,我还遇到了一些其他有关动态属性的问题。T4 !!!-D T4语法起初可能有点吓人,所以仔细阅读该语法是明智的。进行更改时要非常专注也是一个好主意:-)

所以!如果您查看模型,则.edmx文件下会有一个.tt文件。该.tt(T4)文件是实际创建模型类的脚本。每次您构建模型或在模型编辑器中进行一些更改时,脚本都会自动运行。

假设您的模型描述符名为Model1.edmx。在它下面的树中,将有一个名为Model1.Context.tt的文件。您还将看到Model1.Context.cs文件。显然,这是您上下文的实际代码文件。但是,此文件是运行.tt脚本文件的结果!它是完全动态创建的。所以不知道编辑它。

打开.tt文件,您将看到类似以下内容:

<#@ template language="C#" debug="false" hostspecific="true"#>
<#@ include file="EF6.Utility.CS.ttinclude"#><#@
 output extension=".cs"#><#

const string inputFile = @"Model1.edmx";
var textTransform = DynamicTextTransformation.Create(this);
..
..

再向下排50行左右,正在编写构造函数代码。

using System;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
<#
if (container.FunctionImports.Any())
{
#>
using System.Data.Entity.Core.Objects;
using System.Linq;
<#
}
#>

<#=Accessibility.ForType(container)#> partial class <#=code.Escape(container)#> : DbContext
    {
        public <#=code.Escape(container)#>()
            : base("name=<#=container.Name#>")
        {
        base.Configuration.ProxyCreationEnabled = false;
    <#
    if (!loader.IsLazyLoadingEnabled(container))
    {
    #>
            this.Configuration.LazyLoadingEnabled = false;
    <#
    }

我添加了属性,base.Configuration.ProxyCreationEnabled = false;以便它将成为构造函数中的第一行。

保存文件,然后打开Model1.Context.cs文件以查看生成的代码。如果要强制运行模板脚本,请选择菜单

构建-转换所有T4模板

很容易知道您是否在T4代码中犯了一个错误,因为根本不会制作.cs文件,或者如果您在编辑器中打开它,则可能会出现明显的错误。


哇-这确实应该是首选解决方案,因为它从根本上解决了问题。并为* .tt文件与生成的* .cs文件之间的关系提供了良好的背景。
道格拉斯·蒂姆斯
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.