This project has moved and is read-only. For the latest updates, please go here.

EF Mapping

Jan 9, 2014 at 3:00 PM
Edited Jan 9, 2014 at 5:26 PM
I was looking through mapping part.

I'm curious why you chose to implement a tt generator on interfaces over runtime subclassing with a proxy. EF had this approach in older versions and they copied NHibernate approach.
A proxy would allow POCO with a base class so common functionality could be shared across entities.

Also as it stands now tt needs some changes to allow property changes:
Output:
public System.String Name
        {
                    get { 
                     BeforeGetPropertyName();
                     var val = GetRelatedProperty<System.String>("Name"); 
                     AfterGetPropertyName();
                     return val;
                    }
                    set { 
                    BeforeSetPropertyName(value);
                    SetRelatedProperty("Name", value); 
                    AfterSetPropertyName(value);
                    }
        }
    
    
        partial void BeforeGetPropertyName();
        partial void AfterGetPropertyName();
        partial void BeforeSetPropertyName(System.String value);
        partial void AfterSetPropertyName(System.String value);
tt:
public <#= generic#><<#=t#>> <#= p.Name #>
    {
<#+ 
                        if (helper.GetDecoratedInterfaces().Any(x=>x.InterfaceFullName.Equals(t))) 
                        {
                            #>
        get 
        { 
            BeforeGetProperty<#= p.Name #>();
            var val = GetRelatedObjects<<#=t#>>(<#= code.CreateLiteral(p.Name) #>); 
            AfterGetProperty<#= p.Name #>();
            return val;
        }
        set 
        {
            BeforeSetProperty<#= p.Name #>(value);
            SetRelatedObjects(<#= code.CreateLiteral(p.Name)#>, value); 
            AfterSetProperty<#= p.Name #>(value);
        }
                            <#+
                        } 
                        else 
                        {
                            #>
        get 
        { 
            BeforeGetProperty<#= p.Name #>();
            var val = GetRelatedLiteralPropertiesCollection<<#=t#>>(<#= code.CreateLiteral(p.Name) #>);
            AfterGetProperty<#= p.Name #>();
            return val;
        }
        set 
        {
            BeforeSetProperty<#= p.Name #>(value);
            SetRelatedLiteralPropertiesCollection<<#=t#>>(<#= code.CreateLiteral(p.Name)#>, value);
            AfterSetProperty<#= p.Name #>(value);
        }
<#+
                        }
#>
    }
<#+
                    }
                }
                else
                {
                    var itemType = GetPropertyTypeName(p.Type);
#>

    public <#= itemType #> <#= p.Name #>
    {
<#+
                    PushIndent(CodeRegion.GetIndent(2));
                    if (IsValidLiteralType(helper, p.Type)) 
                    {
#>
        get { 
         BeforeGetProperty<#= p.Name #>();
         var val = GetRelatedProperty<<#= itemType #>>(<#=code.CreateLiteral(p.Name)#>); 
         AfterGetProperty<#= p.Name #>();
         return val;
        }
        set { 
        BeforeSetProperty<#= p.Name #>(value);
        SetRelatedProperty(<#=code.CreateLiteral(p.Name)#>, value); 
        AfterSetProperty<#= p.Name #>(value);
        }
<#+
                    } 
                    else 
                    {
                        if (p.Getter != null) WriteSingleGetter(code, p);
                        if (p.Setter != null) WriteSingleSetter(code, p);
                    }
                    PopIndent();
#>
    }


    partial void BeforeGetProperty<#= p.Name #>();
    partial void AfterGetProperty<#= p.Name #>();
    partial void BeforeSetProperty<#= p.Name #>(<#= itemType #> value);
    partial void AfterSetProperty<#= p.Name #>(<#= itemType #> value);
Jan 10, 2014 at 3:35 PM
The main reasons for doing it the way we do are:
1) It is simpler to implement
2) It requires no additional dependencies

I am very keen to keep the number of dependencies for core B* to a minimum. To implement dynamic proxies on top of POCOs without introducing a dependency on something like Castle Dynamic Proxies would require extra development time - and there are a bunch of other things that I would put as a higher priority over POCOs.

I'm not sure what your code snippets above are to show - what is the problem that they solve exactly ?
Jan 10, 2014 at 3:58 PM
I need to execute code on generated entity properties getter/setter but I can't do that in generated file so it needs some partial methods that are called in get/set or some other solution. The snippet adds those partial methods.
Jan 10, 2014 at 4:09 PM
I see...I think this actually shows one reason why the tt approach is a nice one - it is pretty easy to extend functionality like this without getting into funky dynamic code generation stuff - its just a question of modifying the text template to write out the entity implementation classes the way you want them.