DCSIMG
T4 Templates in Entity Framework 4 - Gil Fink's Blog

Gil Fink's Blog

Fink about IT

News

Microsoft MVP

My Facebook Profile My Twitter Profile My Linkedin Profile

Locations of visitors to this page

Creative Commons License

Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.
© Copyright 2013 Gil Fink

Hebrew Articles

Index Pages

My OSS Projects

English Articles

T4 Templates in Entity Framework 4

T4 Templates in Entity Framework 4

T4 templates orT4 Templates in Entity Framework 4
Text Template
Transformation Toolkit
is
a mean of creating a code
generation
artifacts which
can save a lot of time.
This technology is a part of
Visual Studio since 2005 but
was one of those technologies
that were kept in secret by Microsoft.
Almost all the code generation stuff that is being used
in Visual Studio in technologies such as MVC, Entity Framework,
LINQ to SQL and many other use those templates as backbone
to generate code. In this post I’m going to show one of the
new features of EF4 which is the use of T4 templates to extend
or manipulate the code generation. If you like to read more about
T4 templates I recommend Scott Hanselman’s post – 
T4 (Text Template Transformation Toolkit) Code Generation -
Best Kept Visual Studio Secret
which has many references to good
reading stuff.

T4 Templates in Entity Framework 4 Example

In EF4 we can use T4 templates to extend and manipulate the
code generation. In the example I start with a very simple
console application. That application has a Entity Data Model
which is the same School model that I used for all my previous
EF posts:
Solution Explorer 

Adding a T4 Template

Now lets explore the process of using the T4 templates.
In order to use the T4 templates, from the Entity Framework
Designer
surface use the right mouse button to open the menu
and choose the Add Code Generation Item menu item:
Add Code Generation Item 
This will open the Add New Item window that holds only EF4 T4
templates
:
Add New Item
As you can see I have two T4 templates that I can generate. I choose the
ADO.NET EntityObject Generator. A security warning will be popping up to
check if you trust the source that generated the T4.
Security Warning
I choose to continue and a new file with the extension .tt is added to
the solution.
After Adding the T4 Template
When you observe the generated .tt file you can see that all the generated
stuff of EF is located in a new .cs file that is attached to it. When opening  
the SchoolModel.Designer.cs file that is attached to the edmx file you will
see a comment that say it is no longer being used:

// Default code generation is disabled for model 'path\SchoolModel.edmx'. 
// To enable default code generation, change the value of the 'Code Generation Strategy' designer
// property to an alternate value. This property is available in the Properties Window when the model is
// open in the designer.

Now that we have our own code generation file we can start manipulating
the generated code.

Manipulating Generated Code Using a T4 Template

Say for example that I want to remove the generated OnContextCreated
method which is called from the ObjectContext’s constructors:

/// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    public partial class SchoolEntities : ObjectContext
    {
        #region Constructors
    
        /// <summary>
        /// Initializes a new SchoolEntities object using the connection string found in the 'SchoolEntities' section of the application configuration file.
        /// </summary>
        public SchoolEntities() : base("name=SchoolEntities", "SchoolEntities")
        {
            this.ContextOptions.LazyLoadingEnabled = true;
            OnContextCreated();
        }
    
        /// <summary>
        /// Initialize a new SchoolEntities object.
        /// </summary>
        public SchoolEntities(string connectionString) : base(connectionString, "SchoolEntities")
        {
            this.ContextOptions.LazyLoadingEnabled = true;
            OnContextCreated();
        }
    
        /// <summary>
        /// Initialize a new SchoolEntities object.
        /// </summary>
        public SchoolEntities(EntityConnection connection) : base(connection, "SchoolEntities")
        {
            this.ContextOptions.LazyLoadingEnabled = true;
            OnContextCreated();
        }
    
        #endregion
    
        #region Partial Methods
    
        partial void OnContextCreated();
    
        #endregion
    
        #region ObjectSet Properties
    
        /// <summary>
        /// No Metadata Documentation available.
        /// </summary>
        public ObjectSet<Course> Courses
        {
            get
            {
                if ((_Courses == null))
                {
                    _Courses = base.CreateObjectSet<Course>("Courses");
                }
                return _Courses;
            }
        }
        private ObjectSet<Course> _Courses;
    
        /// <summary>
        /// No Metadata Documentation available.
        /// </summary>
        public ObjectSet<Department> Departments
        {
            get
            {
                if ((_Departments == null))
                {
                    _Departments = base.CreateObjectSet<Department>("Departments");
                }
                return _Departments;
            }
        }
        private ObjectSet<Department> _Departments;
    
        /// <summary>
        /// No Metadata Documentation available.
        /// </summary>
        public ObjectSet<Enrollment> Enrollments
        {
            get
            {
                if ((_Enrollments == null))
                {
                    _Enrollments = base.CreateObjectSet<Enrollment>("Enrollments");
                }
                return _Enrollments;
            }
        }
        private ObjectSet<Enrollment> _Enrollments;
    
        /// <summary>
        /// No Metadata Documentation available.
        /// </summary>
        public ObjectSet<Person> People
        {
            get
            {
                if ((_People == null))
                {
                    _People = base.CreateObjectSet<Person>("People");
                }
                return _People;
            }
        }
        private ObjectSet<Person> _People;
 
        #endregion
        #region AddTo Methods
    
        /// <summary>
        /// Deprecated Method for adding a new object to the Courses EntitySet. Consider using the .Add method of the associated ObjectSet&lt;T&gt; property instead.
        /// </summary>
        public void AddToCourses(Course course)
        {
            base.AddObject("Courses", course);
        }
    
        /// <summary>
        /// Deprecated Method for adding a new object to the Departments EntitySet. Consider using the .Add method of the associated ObjectSet&lt;T&gt; property instead.
        /// </summary>
        public void AddToDepartments(Department department)
        {
            base.AddObject("Departments", department);
        }
    
        /// <summary>
        /// Deprecated Method for adding a new object to the Enrollments EntitySet. Consider using the .Add method of the associated ObjectSet&lt;T&gt; property instead.
        /// </summary>
        public void AddToEnrollments(Enrollment enrollment)
        {
            base.AddObject("Enrollments", enrollment);
        }
    
        /// <summary>
        /// Deprecated Method for adding a new object to the People EntitySet. Consider using the .Add method of the associated ObjectSet&lt;T&gt; property instead.
        /// </summary>
        public void AddToPeople(Person person)
        {
            base.AddObject("People", person);
        }
 
        #endregion
    }

Opening the .tt file and then removing the OnContextCreated
method call from the constructors and also the generation of the
OnContextCreated partial method will result in the following
ObjectContext:

/// <summary>
/// No Metadata Documentation available.
/// </summary>
public partial class SchoolEntities : ObjectContext
{
    #region Constructors
 
    /// <summary>
    /// Initializes a new SchoolEntities object using the connection string found in the 'SchoolEntities' section of the application configuration file.
    /// </summary>
    public SchoolEntities() : base("name=SchoolEntities", "SchoolEntities")
    {
        this.ContextOptions.LazyLoadingEnabled = true;
    }
 
    /// <summary>
    /// Initialize a new SchoolEntities object.
    /// </summary>
    public SchoolEntities(string connectionString) : base(connectionString, "SchoolEntities")
    {
        this.ContextOptions.LazyLoadingEnabled = true;
    }
 
    /// <summary>
    /// Initialize a new SchoolEntities object.
    /// </summary>
    public SchoolEntities(EntityConnection connection) : base(connection, "SchoolEntities")
    {
        this.ContextOptions.LazyLoadingEnabled = true;
    }
 
    #endregion
 
    #region ObjectSet Properties
 
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    public ObjectSet<Course> Courses
    {
        get
        {
            if ((_Courses == null))
            {
                _Courses = base.CreateObjectSet<Course>("Courses");
            }
            return _Courses;
        }
    }
    private ObjectSet<Course> _Courses;
 
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    public ObjectSet<Department> Departments
    {
        get
        {
            if ((_Departments == null))
            {
                _Departments = base.CreateObjectSet<Department>("Departments");
            }
            return _Departments;
        }
    }
    private ObjectSet<Department> _Departments;
 
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    public ObjectSet<Enrollment> Enrollments
    {
        get
        {
            if ((_Enrollments == null))
            {
                _Enrollments = base.CreateObjectSet<Enrollment>("Enrollments");
            }
            return _Enrollments;
        }
    }
    private ObjectSet<Enrollment> _Enrollments;
 
    /// <summary>
    /// No Metadata Documentation available.
    /// </summary>
    public ObjectSet<Person> People
    {
        get
        {
            if ((_People == null))
            {
                _People = base.CreateObjectSet<Person>("People");
            }
            return _People;
        }
    }
    private ObjectSet<Person> _People;
 
    #endregion
    #region AddTo Methods
 
    /// <summary>
    /// Deprecated Method for adding a new object to the Courses EntitySet. Consider using the .Add method of the associated ObjectSet&lt;T&gt; property instead.
    /// </summary>
    public void AddToCourses(Course course)
    {
        base.AddObject("Courses", course);
    }
 
    /// <summary>
    /// Deprecated Method for adding a new object to the Departments EntitySet. Consider using the .Add method of the associated ObjectSet&lt;T&gt; property instead.
    /// </summary>
    public void AddToDepartments(Department department)
    {
        base.AddObject("Departments", department);
    }
 
    /// <summary>
    /// Deprecated Method for adding a new object to the Enrollments EntitySet. Consider using the .Add method of the associated ObjectSet&lt;T&gt; property instead.
    /// </summary>
    public void AddToEnrollments(Enrollment enrollment)
    {
        base.AddObject("Enrollments", enrollment);
    }
 
    /// <summary>
    /// Deprecated Method for adding a new object to the People EntitySet. Consider using the .Add method of the associated ObjectSet&lt;T&gt; property instead.
    /// </summary>
    public void AddToPeople(Person person)
    {
        base.AddObject("People", person);
    }
 
    #endregion
}

Of course this is silly to do because this is an extension point
when the context is being created but for the example it is enough
to show the power of the T4 templates.

Summary

The T4 templates enables us to implement code generation.
When you have something that you do manually more then one time
then applying a T4 template can help you to make it automatic.
As I show in the post, EF4 is shipping with a way to manipulate the
code generation using T4 templates. Next time when something bother
you in the EF generated code you can do something about it.

DotNetKicks Image

Comments

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# December 5, 2009 3:47 PM

Gil Fink on .Net said:

Reading a Xml File in T4 Templates After I wrote the post about the use of T4 templates in EF4 , I played

# December 12, 2009 1:46 PM

Webmaster Crap » Blog Archive » T4 Templates in Entity Framework 4 - Gil Fink on .Net said:

Pingback from  Webmaster Crap  &raquo; Blog Archive   &raquo; T4 Templates in Entity Framework 4 - Gil Fink on .Net

# December 12, 2009 6:11 PM

Tune Up Your PC » Post Topic » Entity Framework 4.0 Resources gets a December 2009 Update said:

Pingback from  Tune Up Your PC  &raquo; Post Topic   &raquo; Entity Framework 4.0 Resources gets a December 2009 Update

# December 17, 2009 7:06 AM

ADO.NET EF: + recursos y trabajo con plantillas T4! « Pasi??n por la tecnolog??a… said:

Pingback from  ADO.NET EF: + recursos y trabajo con plantillas T4! &laquo; Pasi??n por la tecnolog??a&#8230;

# January 18, 2010 12:01 AM

Blog del CIIN said:

Una de las novedades que vienen con la versi&oacute;n 4.0 de ADO.NET Entity Framework es el soporte para

# January 18, 2010 12:01 AM

EF Navigation properties don’t raise OnPropertyChanging and OnPropertyChanged Events - Programmers Goodies said:

Pingback from  EF Navigation properties don&#8217;t raise OnPropertyChanging and OnPropertyChanged Events - Programmers Goodies

# October 4, 2011 1:50 AM