Migrating from EF POCO Adapter to Entity Framework v4.0

Now that Visual Studio 2010 and .NET Framework 4.0 have been released, users of Entity Framework can use POCO objects with Entity Framework without the need for wrapper layers such as EFPocoAdapter. Since I know a number of people are using EFPocoAdapter in their production applications and it is not supported, I recommend they migrate to using native POCO support in EF v4.0 which is the supported way of using POCOs from now on.

This post will highlight the differences between EF and EFPOCOAdapter, which you must keep in mind when migrating your code base.

Note that this list is not guaranteed to be exhaustive and does not imply that there are no other differences.

Change tracking differences

Entity Framework v4.0 supports 3 different "flavors" of POCO objects:

  • Basic (plain) POCOs
  • Lazy loading POCO proxies (non-sealed class, with default constructor and all navigation properties marked as virtual and overrideable)
  • Change tracking POCO proxies (non-sealed class, with default constructor, all properties marked as virtual and overrideable and all collections using ICollection<T> types)

EF will enable particular feature (such as lazy loading and change tracking) if all required conditions have been met and there is no mechanism to explicitly request a particular type of behavior for each property. If the conditions have not been met, EF will fall back to plain POCO behavior.

EFPocoAdapter provides more fine-grained approach – you can set a change tracking mode (Snapshot, Proxy, etc.) for each property individually in CSDL by using objectmapping:ChangeTracking attribute. This is not supported by EF – the user needs to choose between one of the three flavors of POCO and mark properties of the entity accordingly. This ability to explicitly specify a tracking mode for every property might be implemented in future versions of EF.

From the performance standpoint, using change tracking-enabled objects is recommended, but doing so is not always possible, especially when you have code that expects concrete POCO types to be in use (such as WCF serialization). To learn more about this issue and possible workarounds check out this blog post: http://blogs.msdn.com/adonet/archive/2010/01/05/poco-proxies-part-2-serializing-poco-proxies.aspx

Value objects

EFPocoAdapter supports objects which are immutable (can only be constructed, but not modified) and semi-mutable objects when certain properties are read-only and must be initialized in the constructor while some are read-write. Below is an example of an immutable value object:

public class Category   
{   
    public Category(int categoryID, string categoryName)   
    {   
        this.CategoryID = categoryID;   
        this.CategoryName = categoryName;   
    }   
  
    public int CategoryID { get; private set; }   
    public string CategoryName { get; private set; }   
}

EF v4.0 does not allow this directly (it always requires a default constructor without parameters and property setters to be there), but you can persist value objects and read them back by having setters which are non-public (EF will still be able to access them in full trust, but your application will not). You just need to add a non-public default constructor, as in the following example:

public class Category
{
    private Category()
    {
        // this constructor will be called by EF
    }

    public Category(int categoryID, string categoryName)
    {
        this.CategoryID = categoryID;
        this.CategoryName = categoryName;
    }

    public int CategoryID { get; private set; }
    public string CategoryName { get; private set; }
}

This approach has some downsides, because there is no validation happening when object is hydrated from the database (as it is bypassing the construction logic), but you may argue that this is not so bad since the object must have been validated before it was persisted.

Also note that you will need to switch from structures (C# struct) as a representation for value objects to classes, because the former are not supported in EFv4.

Lazy Loading

There are differences in the way lazy loading is implemented. In EF v4.0, collection properties with lazy loading need to be virtual, in POCO adapter they do not but it they have to be ICollection<T> or IList<T>. EFv4 supports lazy loading of concrete collection types (such as List<T>) while POCO adapter does not.

This is an example of a class which has Products property which can be lazy-loaded in Entity Framework:

public class Category
{
    public int CategoryID { get; set; }
    public string CategoryName { get; set; }
    public virtual List<Product> Products { get; set; }
}

Lazy-loaded properties of type ICollection<T> need to be marked as virtual to get lazy loading

Shadow state

Because of the way POCO adapter is implemented, it is also possible do omit certain properties (such as auto-generated GUIDs, etc.) from the POCO model but still have them in CSDL model. This is not something that’s possible in EFv4, so you need to add the properties to your domain classes. As in the case of value objects, properties can be private, but EF needs to be able to see them in order to load your model.

API Differences

The following table lists EF POCO Adapter classes and their EF v4.0 equivalents:

POCO Adapter Type Entity Framework v4.0 Type
EFPocoContext ObjectContext
EFPocoQuery<T> ObjectQuery<T>
IEntitySet<T> IObjectSet<T>
PocoEntitySet<T> ObjectSet<T>
EFCompiledQuery CompiledQuery

Method names of POCO adapter classes typically correspond to method names in Entity Framework v4.0, but since POCO adapter was created at the beginning of EFv4.0 there can be some differences you will need to fix during the migration. Since POCO adapter is generally a subset of EF you should be able to easily find corresponding methods and properties, except:

  • EFPocoContext.EnableLazyLoading – use ContextOptions.LazyLoadingEnabled
  • EFPocoContext.ConvertProxiesToPoco() and EFPocoContext.ConvertPocoToProxies()
  • EFPocoContext.IsProxy()

I’m hoping these hints will be helpful to folks porting their apps to use POCO support in Entity Framework 4.0. If you have any further questions, feel free to ask them here.

Tags: ,

  1. #1 written by Zeeshan Hirani May 5th, 2010 at 21:00

    Interesting post. I never used the adapter but from your explanations it appears that adapter had some cool features that POCO in EF4 missed. Can you elaborate what are the possible features that EF team is considering to add to POCO in the next release?

    Zeeshan

    RE Q
  2. #2 written by Rami May 13th, 2010 at 20:33

    Hi Jarek,

    Thank you for posting this.

    I am in the process of converting from EFPocoAdapter 1.03 to EF4 but I need some help.

    Here are some of my questions:
    1. Does EF4 have something similar to EFPocoClassGen.exe to automatically generate the PocoClasses, PocoAdapter, and PocoContainer from the csdl?

    2. My EFPocoAdapter PocoAdapter class has references to the following types. What are their EF4 equivalent?
    QueryTranslationCache
    PocoAdapterBase
    IPocoAdapter
    IEntityProxy
    PocoEntity
    IListEntityCollectionAdapter

    3. Is it correct to convert GetEntitySet to GetEntitySet ?

    Thanks again,
    -Rami

    RE Q
  3. #3 written by Jarek Kowalski May 13th, 2010 at 21:30

    Hi Rami,

    1. Yes, EF4 has support for generating POCO objects using T4 template. See this post for more information: http://blogs.msdn.com/adonet/pages/walkthrough-poco-template-for-the-entity-framework.aspx

    2. Those types are used internally by EFPocoAdapter and are not present or needed when you use EF4 natively. Feel free to ignore them. In general you will not have pocoadapter class, since POCOs are handled natively by EF4.

    3. That would be ObjectContext.CreateObjectSet();

    RE Q

SetPageWidth