Tales
Tales

Reputation: 1923

Editing T4 template does not change generated code on Models

I needed to override or replace the default constructor of my models for a project using database first approach. After some research I found this answer to be the most appropiate to accomplish what I wanted: Override or replace default constructor when using database first approach.

So, not being an expert, I went to my ProjectModel.edmx and inside I found two files with extension .tt, they were called ProjectModel.Context.tt and ProjectModel.tt, so I figured I needed to edit the second one.

Trying to understand how that worked I found a piece of code that seems to generate the constructor of the class:

 1 <#
 2     var complexProperties = typeMapper.GetComplexProperties(complex);
 3     var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(complex);
 4 
 5     if (propertiesWithDefaultValues.Any() || complexProperties.Any())
 6     {
 7 #>
 8     public <#=code.Escape(complex)#>()
 9     {
10 <#
11         foreach (var edmProperty in propertiesWithDefaultValues)
12         {
13 #>
14         this.<#=code.Escape(edmProperty)#> = <#=typeMapper.CreateLiteral(edmProperty.DefaultValue)#>;
15 <#
16         }
17 
18         foreach (var complexProperty in complexProperties)
19         {
20 #>
21         this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
22 <#
23         }
24 #>
25      Init();
26     }
27 
28     partial void Init();
29 
30 <#
31     }

I added lines 25 and 28, just to make the model be generated with the call to Init() and the method be declared after that.

Now, I went to ProjectModel.edmx which shows the diagram of my database, I right clicked over the diagram and ran Update Model from Database... in the menú. Then I went to the Refresh tab and highlighted Tables and clicked Finish. I was expecting that the new generated files would be similar to this:

namespace Project.Models.DB
{
    using System;
    using System.Collections.Generic;

    public partial class Class1
    {
        public Class1()
        {
            this.Events = new HashSet<Event>();
            Init();
        }

        partial void Init();

        public int id { get; set; }
        public string name { get; set; }
        public string slug { get; set; }
        public bool is_active { get; set; }
        public System.DateTime date_created { get; set; }
        public System.DateTime date_updated { get; set; }

        public virtual ICollection<Event> Events { get; set; }
    }
}

but it didn't work, I am wondering if I need to do something else or if I am editing the correct file. Any guidance would be very appreciated.

Upvotes: 0

Views: 354

Answers (1)

reckface
reckface

Reputation: 5858

Your changes are in the complex type section of the template. Note:

 5     if (propertiesWithDefaultValues.Any() || complexProperties.Any())
 6     {
 7 #>
 8     public <#=code.Escape(complex)#>()
 9     {
10 <#

Look for the iteration of entities, then make your edits there:

foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>(itemCollection))
{
    fileManager.StartNewFile(entity.Name + ".cs");
    BeginNamespace(code);
#>
<#=codeStringGenerator.UsingDirectives(inHeader: false)#> // This may be slightly different based on version of EF, but you get the idea
<#=codeStringGenerator.EntityClassOpening(entity)#>
{
<#
    var propertiesWithDefaultValues = typeMapper.GetPropertiesWithDefaultValues(entity);
    var collectionNavigationProperties = typeMapper.GetCollectionNavigationProperties(entity);
    var complexProperties = typeMapper.GetComplexProperties(entity);

    if (propertiesWithDefaultValues.Any() || collectionNavigationProperties.Any() || complexProperties.Any())
    {
#>
    public <#=code.Escape(entity)#>()
    {
// ... much later
        foreach (var complexProperty in complexProperties)
        {
#>
        this.<#=code.Escape(complexProperty)#> = new <#=typeMapper.GetTypeName(complexProperty.TypeUsage)#>();
<#
        }
#>
    }
    Init();
}
partial void Init();

Upvotes: 1

Related Questions