Code generation is now more than ever a core activity in software development. With the growing complexity of systems and the need to meet deadlines, getting your database access layer generated automatically is crucial, but one can’t forget to groom your tools and update them whenever possible.
CodeSmith has been providing a code generation tool based on .netTiers for a while now, supporting several versions of the .NET framework up to v4.0, but newer versions are still unnatended and that leaves “legacy” code out of all the new features and improvements. With the release of .NET 4.5 and new library updates based on it, namely Enterprise Library 6.0 (EL6.0) and all its sub-libraries, it is important to keep the code generation templates up to date. This guide will attempt to point out all the specific parts of the templates that must be adapted in order for .netTiers to make use of EL6.0 in a file-by-file basis. To follow it you must get EL6.0 from Microsoft (download site) and have a directory with your existing .netTiers templates to work from.
The directory tree must be similar to the following image:
My target environment:
- Visual Studio 2012 (VS)
- .NET 4.5
- Enterprise Library 6.0 (EL)
- Unity Application Block 2.0 (you can change this to 3.0 without effort)
- CodeSmith 7.0.2 (CS)
- .netTiers 2.3.1 (NT)
A few words of notice:
- Migrating between framework or library versions is not easy, and it must be done slowly and with a critical mind, especially on code bound to production systems. If you don’t think that an instruction in this guide applies to your specific case, please do make any changes you deem suitable. As a suggestion, I advise you to read the migration guide to Enterprise Library 6.0 available here.
- Microsoft removed some features available in EL v5.0, namely Caching and Security which were mostly added to .NET itself. This implies that to fully migrate .netTiers to work with v6.0, caching and security features must be re-written from scratch. I consider this out of the scope of this post, so I will just point out places where this affects .netTiers, leaving the implementation open.
- I try to point out the lines you need to change to ease the finding process, but they might be off by a slight margin due to various reasons, so try to look at what is being changed after searching for the line.
From now on, numbered items will represent folders or files in the directory tree (folders will be bold), while dots represent actions that must be followed. Good luck!
- References
- Add a new folder named ‘EntLibv6_0’ and extract your Enterprise Library 6.0 DLLs into it
- VisualStudio
- Copy file ‘entlib.v5_0.config.cst’ and change its name to ‘entlib.v6_0.config.cst’. Edit the renamed file:
- Line 5 – change it to
<%@ Property Name="EntLibVersion" Type="MoM.Templates.EntLibVersion" Default="v6_0" Category="02. Framework Generation - Optional" Description="Indicates the Enterprise Library version to use. Options include v3.1, v5.0 and v6.0" %>
- Comment lines 89 to 99 (related to caching)
<cachingConfiguration defaultCacheManager="<%=BLLNameSpace %>.EntityCache"> <cacheManagers> <add expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="1000" numberToRemoveWhenScavenging="10" backingStoreName="Null Storage" name="<%= BLLNameSpace %>.EntityCache" type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> </cacheManagers> <backingStores> <add encryptionProviderName="" type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.NullBackingStore, Microsoft.Practices.EnterpriseLibrary._entLibVersion %>" name="Null Storage" /> </backingStores> </cachingConfiguration>
- Line 5 – change it to
- Edit file ‘vsnet2005.project.cst’:
- Line 88 – change a) to b)
a) bool includeObjectBuilder = EntLibVersion != MoM.Templates.EntLibVersion.v5_0;
b) bool includeObjectBuilder = EntLibVersion != MoM.Templates.EntLibVersion.v5_0 && EntLibVersion != MoM.Templates.EntLibVersion.v6_0;
- Line 181 – add another condition to the if statement:
VisualStudioVersion == MoM.Templates.VSNetVersion.v2012
- Comment lines 320 to 327:
<Reference Include="Microsoft.Practices.EnterpriseLibrary.Caching, <%= entlibVersionText %>"> <SpecificVersion>False</SpecificVersion> <HintPath><%= LibraryPath %>\Microsoft.Practices.EnterpriseLibrary.Caching.dll</HintPath> </Reference> <Reference Include="Microsoft.Practices.EnterpriseLibrary.Caching.Cryptography, <%= entlibVersionText %>"> <SpecificVersion>False</SpecificVersion> <HintPath><%= LibraryPath %>\Microsoft.Practices.EnterpriseLibrary.Caching.Cryptography.dll </HintPath> </Reference>
- Comment lines 360 to 371:
<Reference Include="Microsoft.Practices.EnterpriseLibrary.Security, <%= entlibVersionText %>"> <SpecificVersion>False</SpecificVersion> <HintPath><%= LibraryPath %>\Microsoft.Practices.EnterpriseLibrary.Security.dll</HintPath> </Reference> <Reference Include="Microsoft.Practices.EnterpriseLibrary.Security.Cache.CachingStore.dll, <%= entlibVersionText %>"> <SpecificVersion>False</SpecificVersion> <HintPath><%= LibraryPath %>\Microsoft.Practices.EnterpriseLibrary.Security.Cache.CachingStore.dll</HintPath> </Reference> <Reference Include="Microsoft.Practices.EnterpriseLibrary.Security.Cryptography, <%= entlibVersionText %>"> <SpecificVersion>False</SpecificVersion> <HintPath><%= LibraryPath %>\Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.dll</HintPath> </Reference>
- Comment lines 883 to 887:
<Compile Include="<%=BLLSubFolder%>IEntityCacheItem.cs"> <SubType>Code</SubType> </Compile> <Compile Include="<%=BLLSubFolder%>EntityCache.cs"> <SubType>Code</SubType> </Compile>
- Line 1094 – change a) for b):
a) <% if(EntLibVersion == MoM.Templates.EntLibVersion.v5_0) { %>
b) <% if(EntLibVersion == MoM.Templates.EntLibVersion.v5_0 || EntLibVersion == MoM.Templates.EntLibVersion.v6_0) { %>
- Line 88 – change a) to b)
- Copy file ‘entlib.v5_0.config.cst’ and change its name to ‘entlib.v6_0.config.cst’. Edit the renamed file:
- NetTiers.cst
- Line 30 – change
'Default="v5_0"'
to'Default="v6_0"'
- Line 31 – change
'Default="v2010"'
to'Default="v2012"'
- Line 32 – change
'Default="v4"'
to'Default="v4_5"'
- To assure that all EL5.0 features are maintained, it is necessary to change all references of a) with b) (lines 1296, 1372, 1449, 1469, 1992)
a) 'if (EntLibVersion == MoM.Templates.EntLibVersion.v5_0)'
b) 'if (EntLibVersion == MoM.Templates.EntLibVersion.v5_0 || EntLibVersion == MoM.Templates.EntLibVersion.v6_0)'
- At line 1308, change a) to b)
a) SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.Caching.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.Caching.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.Caching.Cryptography.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.Caching.Cryptography.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.Logging.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.Logging.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.Logging.Database.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.Logging.Database.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.Security.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.Security.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.Security.Cache.CachingStore.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.Security.Cache.CachingStore.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.dll", libPath + \\Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.dll);
b) if(EntLibVersion != MoM.Templates.EntLibVersion.v6_0) { SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.Caching.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.Caching.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.Caching.Cryptography.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.Caching.Cryptography.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.Security.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.Security.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.Security.Cache.CachingStore.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.Security.Cache.CachingStore.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.Security.Cryptography.dll"); } SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.Logging.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.Logging.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.Logging.Database.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.Logging.Database.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.dll"); SafeCopyFile(this.CodeTemplateInfo.DirectoryName + "\\References\\" + entLibSubDir + "\\Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.dll", libPath + "\\Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.dll");
- Comment out the following lines (1432 to 1444):
//---------------------------------------------------------------------------------------------------------------------------------------------- //-- Entity IEntityCacheItem file //---------------------------------------------------------------------------------------------------------------------------------------------- XmlElement iEntityCacheItemNode = AddFileNode(commonNode, "IEntityCacheItem.cs"); this.GetTemplate("IEntityCacheItem.cst").SetProperty("NameSpace", BLLNameSpace); this.RenderToFile("IEntityCacheItem.cst", rootPathBLL + "\\IEntityCacheItem.cs", true); //---------------------------------------------------------------------------------------------------------------------------------------------- //-- Entity EntityCache file //---------------------------------------------------------------------------------------------------------------------------------------------- XmlElement iEntityCacheNode = AddFileNode(commonNode, "EntityCache.cs"); this.GetTemplate("EntityCache.cst").SetProperty("NameSpace", BLLNameSpace); this.RenderToFile("EntityCache.cst", rootPathBLL + "\\EntityCache.cs", true);
- Line 30 – change
- TemplateLib
- FrameworkTemplace.cst
- Add entry
<%@ Register Name="entlibv6_0config" Template="../VisualStudio/entlib.v6_0.config.cst" MergeProperties="False" ExcludeProperties="" %>
- Add entry
- CreateTemplate.cs
- Add entry
CodeTemplates.Add("entlib.v6_0.config.cst", base.CreateTemplate<entlibv6_0config>()); this.PerformStep();
- Add entry
- CommonSqlCode.cs
- Add to the switch inside method GetEntLibVersionSignature(EntLibVersion version):
case MoM.Templates.EntLibVersion.v6_0 : entlibVersionText = "Version=6.0.1304.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; break;
- Add to the switch inside method GetUnityVersionSignature(EntLibVersion version):
case MoM.Templates.EntLibVersion.v6_0 : unityVersion = "Version=2.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; break;
- Add to the switch inside method GetServiceLocationVersionSignature(EntLibVersion version):
case MoM.Templates.EntLibVersion.v6_0 : unityVersion = "Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"; break;
- Add to the switch inside method GetEntLibOBVersionSignature(EntLibVersion version):
case MoM.Templates.EntLibVersion.v6_0 : entlibOBVersionText = string.Empty; break;
- Add to the switch inside method GetEntLibOBClassName(EntLibVersion version):
case MoM.Templates.EntLibVersion.v6_0: entlibOBClassName = string.Empty; break;
- Add to the switch inside method GetMSBuildExtensionsVersionString(VSNetVersion version):
case ( VSNetVersion.v2012 ) : versionNumber = "11.0"; break;
- Add to the switch inside method GetVisualStudioSolutionFileVersionString(VSNetVersion version):
case ( VSNetVersion.v2012 ) : versionNumber = "12.0"; break;
- Add to the switch inside method GetVisualStudioProductVersionString(VSNetVersion version):
case ( VSNetVersion.v2012 ) : toolsVersion = "4.5"; break;
- Add to the switch inside method GetVisualStudioToolVersionString(VSNetVersion version):
case ( VSNetVersion.v2012 ) : versionNumber = "11.0.50727"; break;
- Add to the switch inside method GetVisualStudioNameString(VSNetVersion version):
case ( VSNetVersion.v2012 ) : versionNumber = "2012"; break;
- Add to the switch inside method GetVisualStudioGeneralVersionString(DotNetFrameworkVersion
version):case ( VSNetVersion.v2012 ) : versionNumber = "11.0.0.0"; break;
- Add to the switch inside method GetDotNetFrameworkString(VSNetVersion version):
case ( DotNetFrameworkVersion.v4_5 ) : versionNumber = "4.5"; break;
- Add to EntLibVersion enum:
/// <summary>Use Enterprise Library version 6.0</summary> v6_0 = 16
- Add to VSNetVersion enum:
v2012
- Add to DotNetFrameworkVersion enum:
/// <summary> version 4.5 </summary> v4_5
- Add to the switch inside method GetEntLibVersionSignature(EntLibVersion version):
- FrameworkTemplace.cst
- Entities
- EntityManager.cst
- Comment lines 100 to 106
//bool isCacheable = defaultType.GetInterface("IEntityCacheItem") != null; //see if entity is cachable, if IEntityCacheItem //retrieve from cache. //if (isCacheable) // entity = EntityCache.GetItem<Entity>(key.ToString());
- Comment lines 141 to 142
//if (entity.GetType().GetInterface("IEntityCacheItem") != null) // EntityCache.AddCache(key, entity);
- Comment lines 100 to 106
- EntityManager_EntLib5.cst
- Comment lines 98 to 103
//bool isCacheable = defaultType.GetInterface("IEntityCacheItem") != null; //see if entity is cachable, if IEntityCacheItem //retrieve from cache. //if (isCacheable) // entity = EntityCache.GetItem<TEntity>(key.ToString());
- Comment lines 139 to 140
//if (entity.GetType().GetInterface("IEntityCacheItem") != null) // EntityCache.AddCache(key, entity);
- Comment lines 98 to 103
- Validation
- PropertyValidator.cst
- Lines 190, 198 and 212, change a) for b)
a) <%if(EntLibVersion != MoM.Templates.EntLibVersion.v5_0) { %>
b) <% if(EntLibVersion != MoM.Templates.EntLibVersion.v5_0 && EntLibVersion != MoM.Templates.EntLibVersion.v6_0) { %>
- Lines 190, 198 and 212, change a) for b)
- PropertyValidator.cst
- EntityManager.cst
- DataAccessLayer
- Bases
- EntityProviderBaseCoreClass.generated.cst
- Line 33, change a) for b)
a) <% if(EntLibVersion != MoM.Templates.EntLibVersion.v5_0) { %>
b) <% if(EntLibVersion != MoM.Templates.EntLibVersion.v5_0 && EntLibVersion != MoM.Templates.EntLibVersion.v6_0) { %>
- Line 33, change a) for b)
- EntityProviderBaseCoreClass.generated.cst
- Bases
- Components
- ServiceBaseCore.cst
- Line 38, change a) for b)
a) <% if(EntLibVersion == MoM.Templates.EntLibVersion.v5_0) { %>
b) <% if(EntLibVersion == MoM.Templates.EntLibVersion.v5_0 || EntLibVersion == MoM.Templates.EntLibVersion.v6_0) { %>
- Line 38, change a) for b)
- SecurityContextBase.cst.
NOTE: This file generates code that relies on Security features that are no longer available in Enterprise Library 6.0, to it must be re-implemented from scratch- Line 20 – comment
'using Microsoft.Practices.EnterpriseLibrary.Security;'
- Line 35 – comment
'private IAuthorizationProvider ruleProvider = null;'
- Line 36 – comment
'private ISecurityCacheProvider securityCacheProvider = null;'
- Line 70 – comment property
RuleProvider
Line 109 – comment the contents of the method'IsAuthorized'
, leaving only'return true'
to maintain compatibility with callers
- Line 20 – comment
- SecurityContext.cst
- Line 20 – comment
'using Microsoft.Practices.EnterpriseLibrary.Security;'
- Line 20 – comment
- ContextView.cst
- Line 20 – comment
'using Microsoft.Practices.EnterpriseLibrary.Security;'
- Line 20 – comment
- ServiceBaseCore.cst
Any comments, suggestions and problems found please share them in the comments below.
That’s it! You should now be able to generate your data access layer targeting .NET 4.5 and Enterprise Library 6.0 as you would do before with .NET 4.0 and Enterprise Library 5.0 (don’t forget to re-check your template settings before starting generating away).
It would be great if you posted your modified nettiers for download here. Thanks.