共用方式為


Using DbContext in EF 4.1 Part 8: Working with Proxies

 


The information in this post is out of date.

Visit msdn.com/data/ef for the latest information on current and past releases of EF.

For Proxies see https://msdn.com/data/jj592886


 

Introduction

Version 4.1 of the Entity Framework contains both the Code First approach and the new DbContext API. This API provides a more productive surface for working with the Entity Framework and can be used with the Code First, Database First, and Model First approaches. This is the eighth post of a twelve part series containing collections of patterns and code fragments showing how features of the new API can be used.

The posts in this series do not contain complete walkthroughs. If you haven’t used EF 4.1 before then you should read Part 1 of this series and also Code First Walkthrough or Model and Database First with DbContext before tackling this post.

Working with proxies

When creating instances of POCO entity types, the Entity Framework often creates instances of a dynamically generated derived type that acts as a proxy for the entity. This proxy overrides some virtual properties of the entity to insert hooks for performing actions automatically when the property is accessed. For example, this mechanism is used to support lazy loading of relationships—see Part 6 of this series.

Disabling proxy creation

Sometimes it is useful to prevent the Entity Framework from creating proxy instances. For example, serializing non-proxy instances is considerably easier than serializing proxy instances. Proxy creation can be turned off by clearing the ProxyCreationEnabled flag. One place you could do this is in the constructor of your context. For example:

 public class UnicornsContext : DbContext
{
    public UnicornsContext()
    {
        this.Configuration.ProxyCreationEnabled = false;
    } 

    public DbSet<Unicorn> Unicorns { get; set; }
    public DbSet<Princess> Princesses { get; set; }
}

Note that the EF will not create proxies for types where there is nothing for the proxy to do.  This means that you can also avoid proxies by having types that are sealed and/or have no virtual properties.

Explicitly creating an instance of a proxy

A proxy instance will not be created if you create an instance of an entity using the new operator. This may not be a problem, but if you need to create a proxy instance (for example, so that lazy loading or proxy change tracking will work) then you can do so using the Create method of DbSet. For example:

 using (var context = new UnicornsContext())
{
    var unicorn = context.Unicorns.Create();
}

The generic version of Create can be used if you want to create an instance of a derived entity type. For example:

 using (var context = new NorthwindContext())
{
    var discontinuedProduct = context.Products.Create<DiscontinuedProduct>();
}

Note that the Create method does not add or attach the created entity to the context.

Note that the Create method will just create an instance of the entity type itself if creating a proxy type for the entity would have no value because it would not do anything. For example, if the entity type is sealed and/or has no virtual properties then Create will just create an instance of the entity type.

Getting the actual entity type from a proxy type

Proxy types have names that look something like this:

System.Data.Entity.DynamicProxies

.Unicorn_5E43C6C196972BF0754973E48C9C941092D86818CD94005E9A759B70BF6E48E6

You can find the entity type for this proxy type using the GetObjectType method from ObjectContext. For example:

 using (var context = new UnicornsContext())
{
    var unicorn = context.Unicorns.Find(1);
    var entityType = ObjectContext.GetObjectType(unicorn.GetType());
} 

Note that if the type passed to GetObjectType is an instance of an entity type that is not a proxy type then the type of entity is still returned. This means you can always use this method to get the actual entity type without any other checking to see if the type is a proxy type or not.

Summary

In this part of the series we looked at how to switch off proxy creation, how to explicitly create a proxy instance, and how to get the actual entity type from a proxy type.

As always we would love to hear any feedback you have by commenting on this blog post.

For support please use the Entity Framework Forum.

Arthur Vickers

Developer

ADO.NET Entity Framework

Comments

  • Anonymous
    February 02, 2011
    If only there was a way to automagically do this without the virtual properties and proxies (.NET Profiler API?  PostSharp or other AOP frameworks?  Code/IL generation/modification?).  Maybe you could talk to the language or compiler teams about some way to do that for vNext (it would be useful for testing/mocking frameworks as well).  Then this would be perfect. :)

  • Anonymous
    February 02, 2011
    So nice to see EF become a very nice ORM

  • Anonymous
    February 07, 2011
    @shawn This is a frequent topic of conversation on the EF team and we hope to be able to do something at some point, but with so many other feature requests as well I'm not sure if/when it will happen. @tobi Thanks. :-)

  • Anonymous
    February 11, 2011
    @Aurthur: Makes sense.  Although depending on how you look at things, it could be seen as a foundational piece since requiring virtual modifiers for lazy-loading is one of the last things keeping the entities from being truly persistent ignorant POCOs (along with maybe the ability to use an IList or a concrete collection for lists of related entities). Plus the virtuals are easy to accidentally forget and cause bugs (not that I've ever done that). ;) Anyway, great work on the framework and this series of posts, and it's wonderful to have the extra transparency and opportunity to give feedback!

  • Anonymous
    May 03, 2011
    I couldn't find a way to access ObjectContext. Could someone point me in the right direction. Thanks

  • Anonymous
    January 24, 2012
    @shawn: We hear you; thanks for the feedback. @Rahul: DbContext explicitly implements the IObjectContextAdapter interface. To get the ObjectContext cast your context to IObjectContextAdapter and use the ObjectContext property. Thanks, Arthur

  • Anonymous
    August 20, 2012
    If I turnoff ProxyConfigurationEnabled to false my unit tests on controller actions which call DBContext to invoke SP are not working.  The functionality itself executes fine, but Unit tests throw AccessViolationException. Any suggestions ?

  • Anonymous
    August 21, 2012
    @Aparna - Can you start up a Stack Overflow thread with the 'entity-framework' tag and include a code example that reproduces the issue.