ChatGPT解决这个技术问题 Extra ChatGPT

What are the downsides to turning off ProxyCreationEnabled for CTP5 of EF code first

The only way that my WCF service can return classes from a code first model is by setting the ProxyCreationEnable to false using the code below.

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

What are the negative consequences of doing this? One gain is that I can at least get these dynamic types serialized so they can be sent over the wire using WCF.

"WCF service can return classes from a code first model" - you really shouldn't be using domain/entity types as DTOs anyway. DTOs are not business objects.

A
ALT

If DbContext.Configuration.ProxyCreationEnabled is set to false, DbContext will not load child objects for some parent object unless Include method is called on parent object. Setting DbContext.Configuration.LazyLoadingEnabled to true or false will have no impact on its behaviours.

If DbContext.Configuration.ProxyCreationEnabled is set to true, child objects will be loaded automatically, and DbContext.Configuration.LazyLoadingEnabled value will control when child objects are loaded.


L
Ladislav Mrnka

Dynamic proxies are used for change tracking and lazy loading. When WCF tries to serialize object, related context is usually closed and disposed but serialization of navigation properties will automatically trigger lazy loading (on closed context) => exception.

If you turn off lazy loading you will need to use eager loading for all navigation properties you want to use (Include on ObjectQuery). Tracking changes doesn't work over WCF it works only for modification of entity which is attached to ObjectContext.


Is there a performance benefit to disabling ProxyCreationEnabled? I frequently grab a DbContext instance just to do a read with eager loading, for example.
@ChrisMoschini "When a POCO entity does not have a change tracking proxy, changes are found by comparing the contents of your entities against a copy of a previous saved state. This deep comparison will become a lengthy process when you have many entities in your context, or when your entities have a very large amount of properties, even if none of them changed since the last comparison took place." msdn.microsoft.com/en-us/library/hh949853(v=vs.113).aspx
@NiklasPeter Conversely, from the same link you provided: "Note that creating a proxy entity will typically be more expensive than creating a non-proxy POCO entity due to the added set of events created by Entity Framework." - of course, never speculate: profile first.
M
My Stack Overfloweth

When you use EF, it creates a proxy by default for your class. A solution can be to add this line in the constructor of your DbContext class. Your data model inherited from the DbContext class, so you can edit your model like this:

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

This class is in your EF.edmx then in the yourmodel.Context.tt then yourmodel.Context.cs


This is not an answer but it helped me anyway.
Do you have a good suggestion on how to automate the process of putting in that line? Every time I'll recreate a model, I'm surely bound to forget to set the property to false and that can take hours of debugging before someone realizes what's wrong with it.
@konrad - Create the code in a partial class so it does not get overridden. public partial class yourDataMoldelEntities()
@Mikee Really? I would expect some kind of problems due to the auto-generated constructor colliding with the one written by me in the partial class...
@konrad they created the partial class 'type' to give you a wayto not have your code overwritten
P
Per Malmstedt

(Using Visual Studio 2013 or later)

To avoid the edit of the class constructor in your EF model every time you refresh the model from the database, or some other way trigger the rebuild of the code, the proper place to do the change is in the T4 code file that is responsible of actually creating the model code. I had some other issue with dynamic properties a few years back when I understood the underlying mechanics of how the classes and properties was actually created. T4!!! What a miracle it is :-D T4 syntax can be a bit intimidating at first, so reading up on the syntax is wise. Being VERY focused when making changes is also a good idea :-)

So! If you look in your model, you have a .tt file under your .edmx file. This .tt (T4) file is the script that actually creates your model class. The script will be run automatically each time you build your model or make some changes in the model editor.

Let's say your Model descriptor is named Model1.edmx. You will have a file named Model1.Context.tt in the tree under it. You will also see a Model1.Context.cs file. This is obviously the actual code file for your context. But this file is the result of the .tt script file being run! It is completely dynamically created. So no idea editing it.

Open the .tt file and you will see something like:

<#@ 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);
..
..

Another 50 or so lines down, the constructor code is being scripted.

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;
    <#
    }

I have added the property base.Configuration.ProxyCreationEnabled = false; so that it will be the very first line in the constructor.

Save your file, and open the Model1.Context.cs file to see the resulting code. If you want to force the template script to run, select the menu

Build - Tranform all T4 templates

It is easy to know if you've made a mistake in your T4 code, as the .cs file will be either not made at all, or with obvious errors if you open it in the editor.


Wow - this really should be the preferred solution since it fixes the problem at the root. And also provides a good background on the relationship of the *.tt file with the resulting *.cs file.