Why are the DbContext T4 templates so different from the EF4 POCO templates?

A while ago Julie Lerman asked the question above and then suggested that the response should be blogged—so, better late than never, here’s the post.

Of course, the most obvious difference is that the DbContext templates use DbContext while the EF4 POCO templates use ObjectContext. But beyond that, the POCO templates have a lot of code that attempts to do fixup of properties and relationships even when the entity is not attached to the context. The DbContext templates have none of this code. Why?

The answer is that it was a difference in philosophy between how we created the two templates. For the original POCO templates we went with the approach of making them do everything that we could even though they were POCO. So with these templates you get change tracking proxies and fixup in the templates. There turned out to be several downsides with this, one being that the templates became very complex and while the entity classes were technically still POCO they became less “pure” POCO because of all the EF-generated code built into them. Another downside was that they generated change tracking proxies by default. Change tracking proxies are great for some scenarios, but we have observed that in the majority of situations using just lazy-loading proxies reduces complexity and works better. Also, when using change tracking proxies and fixup in the same entities you often have both the EF stack and the proxies trying to do the same fixup at the same time, which causes additional problems.

So for the DbContext templates we took a different approach and created templates that generated entities and a context that is really, really simple. This means that when you get your classes and look at them you can immediately see everything that they do—something that cannot be said for any of the other types of entities that we generate. This also means that the templates are quite simple, which makes it easier for people to use them as a starting point for their own customizations. They don’t do fixup, but that seldom seems to be a problem for most types of app, especially because the context does fixup quite frequently—essentially, whenever DetectChanges is called, which happens quite often when using DbContext.

So the bottom line is that for most people the DbContext templates and the entity classes that they generate are a better starting point for domain models than the POCO templates and their entity classes.

Thanks for reading!
Arthur

Advertisements

4 comments on “Why are the DbContext T4 templates so different from the EF4 POCO templates?

  1. Rolland says:

    Arthur, thanks for the insight. I have another question about the DBContext T4 templates. Context class the entites are created as ObservableCollection. This is extreamly convenient when using WPF and databinding since it implements INotifyCollectionChanged. However, in the entities if they have a relation with additional entities they are created as iCollection with a default value of a HashSet. I understand the performance value of using the HashSet and the convenience of a HashSet automatically ensuring only unique objects to be added to the set. However, it does not provide, I my limited understanding, for any change notification. This means when binding the child entities to say a listbox it does not automatically get updated. So now to the actually question. What are your thoughts about possible changes to the template to allow for the child entities to raise INotifyCollectionChanged and IPropertyChanged notifications? I have looked at replacing the navigation entites to use ObservableCollection or implementing the INotifyCollectionChanged in a custom HashSet class. Going with the ObservableCollection change seems to require that a custom class be used that mimics the HashSet behavior of prohibiting duplicate objects from being added to the class. Going with the custom HashSet requres that all the methods for modifying the set be Shadowed since they can not be Overridden. Unfortunately, I am not experienced enough to be sure that there are not some serious drawbacks to either of these approaches or if there are any other better ways to enable the child entities to provide change notification.

    I appreciate your thoughts.

    • @Rolland If I were doing databinding, then I would use ObservableCollection for my nav props–this post contains a few more details. However, most apps don’t do databinding in this way–consider, for example MVC apps or anything using a Repository. In addition, ObservableCollection has poor performance as the number of items in the collection gets into the thousands. So we didn’t make it the default for these reasons. It should be simple to go into the T4 file and modify it to generate ObservableCollection instances instead of HashSet.

      If your buisness logic may add duplicates then you can create a simple class derived from ObservableCollection and use it instead. We have something like this for some of the other templates:

      // A System.Collections.ObjectModel.ObservableCollection that raises
      // individual item removal notifications on clear and prevents adding duplicates.
      public class FixupCollection : ObservableCollection
      {
      protected override void ClearItems()
      {
      new List(this).ForEach(t => Remove(t));
      }

      protected override void InsertItem(int index, T item)
      {
      if (!Contains(item))
      {
      base.InsertItem(index, item);
      }
      }
      }
      Hope this helps.

      Thanks,
      Arthur

  2. David Cater says:

    I am trying to use EF 4.3.1 to create an application using code-first techniques. I’m trying to serialize my objects (in order to clone them within my database), and I want to keep using the dynamically generated proxy classes. I’m trying to use the DataContractSerializer, and am trying to get the serializer to track references by using [DataContract (IsReference=True)] on my POCO classes. This fails, because the proxy classes aren’t decorated with [DataContract(IsReference=True)].

    That’s my scenario. My question is: how do I modify the T4 file that governs creation of the proxy classes? Where is it? I’ve found various articles that seem to indicate this is possible, but I’ve never modified T4 files before and can’t figure out where to start looking for them. And I suppose the corollary question is: is modifying the T4 file a good idea in this scenario?

    Thanks,

    David Cater

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s