This is a migrated thread and some comments may be shown as answers.

Prefixing the private backing variables in T4 template

4 Answers 116 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
This question is locked. New answers and comments are not allowed.
Brian Pratt
Top achievements
Rank 1
Brian Pratt asked on 01 Feb 2011, 10:01 PM
I have a database that unfortunately has a column in it called "value", which breaks the code generation.

I am using T4 templates for this, so I thought I'd prefix the private backing variable with an underscore ("_").   Now, I get a build error saying that it now cannot find any of the private members.

Example:
Column Name before: value  (this breaks the property setter with value = value)
T4 changes it to: _value
Visual Studio now gives error:  Error 58 Cannot find field for specified single field id field 'value' at class 'ComNet.Paging.Client.PagingData.OpenAccess.ZoneDevice'. C:\TFSSource\DVAMS 4.0\Development\Paging\DvamsClient\PagingData\obj\Debug\ComNet.Paging.Client.PagingData.dll ComNet.Paging.Client.PagingData

(the error would show up for any property, not just value, so _name would throw same error, but it would look for "name")

It seems that something in the engine is looking for the private variable name?

Anyway, Im stuck.  Any help would be appreciated
Thanks,
Brian

4 Answers, 1 is accepted

Sort by
0
Brian Pratt
Top achievements
Rank 1
answered on 02 Feb 2011, 02:59 PM
I fixed the private keyword problem by adding a "this." to all the private references in the template.  I removed the prefix underscore, reverting back to the original template.  I think the installed template should be modified to to have this as the default way to reference the private member anyway.

On a related note, why does the OpenAccess care if I change the name of a private variable in the template.  It should have absolutely no bearing on the rest of the code that is executed (it is private to the class after all).  Any reason why?

(in Specific.ttinclude, Method "GenerateProperty")

// Paraphrasing with this code... the template does not look exactly like this
get
{
    return this.<#= privatePropertyName #>;
}
set
{
    this.<#= privatePropertyName #> = value;
}


Thanks,
Brian
0
Brian Pratt
Top achievements
Rank 1
answered on 02 Feb 2011, 04:54 PM
Ok, I think I have figured out why the private variable name matters. (and I dont like it, but hopefully I'm wrong in some way)
  • OA does this thing called "Enhancement" _AFTER_ the build is complete.
  • This "Enhancement" injects code into the assembly
  • This code is responsible for setting PRIVATE values on the class (WHY!?!??!?)
  • This enhancement of values is apparently HARD CODED to look for specific private variable names in the T4 template
So, now my questions are:
  • Why do you let us change the private variables in the T4 template if it will wreck the code?
  • Why not in the "Enhancement" use the public PROPERTIES, instead of private members?
  • Use of the public properties would let us do whatever we wanted with incoming data in the get;set;
  • (for example, I want to add a 3rd party Undo/Redo capability directly in the generated code that needs to wrap the private backing variable in an undo object)
  • Or better yet, move the enhanced code into the template... then I could do whatever I want.
This really hamstrings the T4 code generation.  Anyway, hopefully I don't fully understand how to get things working and there is some workaround.  And sorry for the rant... it just seems like everytime I take a step forward with OA, something else bites me.

Thanks,
Brian
0
Alexander
Telerik team
answered on 04 Feb 2011, 02:41 PM
Hello Brian,

Could you please clarify what T4 templates you are using - have you customized the default or implemented new ones? The T4 templates that are installed with OpenAccess always add the this clause in property definitions. This is indeed the correct way to avoid the "value" problem, as you have already found out.

OpenAccess uses the private fields at runtime because they are actually the carriers of the information, not the properties. The properties are only wrappers of the private fields which could be modified by the user and this could lead to various runtime problems. And I am afraid we have no plans to change this behavior.
The enhancement is done after compilation and is not part of the code generation templates because this way the persistent classes have simpler definitions and the OpenAccess specific code cannot be modified by the user.

If you could share a bit more information about what you are trying to achieve, maybe we will be able to help you find the best solution.

Regards,
Alexander
the Telerik team
Accelerate your learning with industry's first Telerik OpenAccess ORM SDK. Download today.
0
Brian Pratt
Top achievements
Rank 1
answered on 04 Feb 2011, 03:02 PM
The templates I am using came from this folder:
I am using the version from the beginning of December 2010.
C:\Program Files\Telerik\OpenAccess ORM\dsl2010\CodeGenerationTemplates\CSharp

I copied them to my project, and modified the OA file to point to these new templates.  (and changed the paths in the templates themselves to point to this folder).  I did have to add the "this." to the private variables.

What I am trying to accomplish:
I am using an undo redo framework called DejaVu, which requires the backing variables to be wrapped in a generic "UndoRedo<int> privatevar".  These need to be default set up to a "new UndoRedo<int>(defaultvalue)".  If I make any modification to the naming scheme of the privatevar, OA crashes on code injection, because it looks for the actual column name instead of the private variable name.  I tried wrapping the private var up in property (trying to trick OA into using it as a regular variable), but it didnt like that either. (On a related note, this would be a great new product for you to release "RadUndo".  A simple to use undo redo framework, that integrates with OA.)

I ended up throwing out OA (again) and going back to Linq2Sql, using T4 toolbox.  It pretty much let me do all I wanted, even tho it injects code like OA does, it seems to be a little smarter about it.  I can rename private variables and L2S seems to figure out that I renamed them, and use the undo redo framework L2S knows how to initialize the private variables.  The only problem I have with L2S is switching between SQLCE and SQL server (OA was simpler in that regard).  

// when I wrap the private var, OA complains about deviceName not being a string on code injection
//  I also tried to make two private variables, and syncing them but still ended up with the problem of
// getting the value in the first place into undo object.
private UndoRedo<string> deviceName = new UndoRedo<string>("default device");
public string DeviceName
{
    get { return deviceName.Value; }
    set {
        using (UndoRedoManager.Start())
        {
            deviceName.Value = value;
            UndoRedoManager.Commit();
        }
    }
}

Tags
General Discussions
Asked by
Brian Pratt
Top achievements
Rank 1
Answers by
Brian Pratt
Top achievements
Rank 1
Alexander
Telerik team
Share this question
or