I am having a hard time to properly set up the environment for T4 to recognize the Sqlite provider. Steps I have taken:
Add assemblies and imports to in .tt
<## assembly name="\System.Data.SQLite.dll" #>
<## import namespace="System.Data.SQLite" #>
At the beginning of tt, add SQLite as one of the providers.
// add sqlite
try
{
var dataSet = ConfigurationManager.GetSection("system.data") as System.Data.DataSet;
dataSet.Tables[0].Rows.Add("SQLite Data Provider"
, ".Net Framework Data Provider for SQLite"
, "System.Data.SQLite"
, "System.Data.SQLite.SQLiteFactory, System.Data.SQLite");
}
catch (System.Data.ConstraintException) { }
I verified in SQLite is one of the providers in DbProviderFactories.
This didn't get SQLite to load by T4. Under a normal application, a SQLite entry would be added to the App.config section. SQLite somehow preloads a native dll. I suspect the preloading is the problem.
After some digging, I resolved the problem by installing System.Data.Sqlite. The installer puts the library in the GAC. The additional code above is not necessary. I was trying to avoid the GAC, but didn't find another way out.
Related
I am trying to write a console program that takes the file name of a T4 template as a parameter, and then processes the template. This because I want users to be able to update the template without having to recompile the program.
The simplest solution I found was to create a second template within Visual Studio that precompiles to a C# class, which in turn executes my external template "Template.tt":
<## template language="C#" hostspecific="True" #>
<## import namespace="System.IO" #>
<## import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#
string template = File.ReadAllText(Host.ResolvePath("Template.tt"));
Engine engine = new Engine();
string output = engine.ProcessTemplate(template, Host);
Write(output);
#>
Within the Program.cs of my console program, I then execute this "calling" template:
string templateText = new Caller().TransformText();
Problem is that when I run this (F5), it throws a NullReferenceException on the first line in my caller template, because Host is null.
However, I thought that setting hostspecific to True would give me a Host.
What do I need to do to get a Host? Don't really want to roll my own.
Alternatively, is there a better way to execute an external T4 template?
According to the MSDN documentation the hostspecific attribute only provides access to the Host-Property inside the t4 template. It does not guarantee the presence of a host. For design-time templates (that are transformed in visual studio) Visual Studio and it's T4 engine provides this host. Unfortunately the Microsoft.VisualStudio.TextTemplating.dll is not a redistributable assembly. So you won't have that host in a run-time scenario.
As you stated, you would need to write a complete T4 engine and host yourself...
If your users need to write/alter the t4 templates, they have knowledge about programming and writing text templating. Could you think of a way to make them use visual studio in any way?
Alternatively (if the changes those user make are small) you could try to use a precompiled template that works on some other input (xml-file, ini-file, command-line-parameters, ...).
Sorry for not having better news...
The actual custom (command line app based) T4 host is not too difficult to implement, I don't recall off my head where I got the code but here are the links of our T4 modular console-app runner:
https://github.com/abstractiondev/absbuilder
The actual command line host is here:
https://github.com/abstractiondev/absbuilder/blob/master/AbstractionBuilder/CustomCmdLineHost.cs
For referencing the T4 parts, we've ran the tooling with Mono runtime / MonoDevelop environments in Linux, now based on the tests (thats 1-2 years ago), I recall that MonoDevelop's T4 was completely compatible and available as source code with some very sensible licensing (MIT or Apache 2.0 if I recall properly).
I'm trying to use dblinq in my IronPython application but am having some problems getting started. When trying to import dblinq classes,using clr.AddReference() it does not seem to see dblinq.
I can build but not access the library
import clr
clr.AddReference("DbLinq")
clr.AddReference("System.Data.Linq")
from System.Data.Linq import DataContext
exit = raw_input("press any key to quit")
1:
My dblinq source is in a subfolder called Resources
clr.AddReferenceToFileAndPath("Resources/DbLinq.dll") => file not found
clr.AddReference("DbLinq") => could not add reference to dblinq
clr.AddReferenceToFileAndPath("C:/Development/DBLinq2/Dblinq.dll" => success
but still cannot use the classes using from DbLinq import ...
Solution
import clr
clr.AddReferenceToFileAndPath("%s\Resources\DbLinq.dll" %os.getcwd())
clr.AddReference("DbLinq")
from Npgsql import *
from DbLinq import Data
For libraries like DbLinq that come with dependencies or are split into several DLLs/modules you can programmatically add their location to allow the runtime to find all required files.
import sys
sys.path.append(r"C:\Temp\DbLinq-0.20.1")
You can then reference all required assemblies as usual:
clr.AddReference("DbLinq")
If there is one primary assembly you can also use clr.AddReferenceToFileAndPath (with an absolute path) which will implicitly add the referenced assemblies location to the path.
clr.AddReference(r"C:\Temp\DbLinq-0.20.1\DbLinq.dll")
I've been struggling with
Compiling transformation: An assembly with the same identity 'xxxx' has already been imported. Try removing one of the duplicate references.
When using T4 to generate some code at design time - with a couple of different reusable templates saved as .ttinclude files, and shared in a number of different "parent" templates.
I toggle between this, and the alternative when I remove one of the references (in my own ttinclude file) which is :
Compiling transformation: The type or namespace name 'yyy' could not be found (are you missing a using directive or an assembly reference?)
Going round in circles, any ideas?
Well, found a dirty workaround.
Would love a better solution / approach, if someone has some advice?
Posting my process as might be helpful to someone else.
Used the template directive to put my templates and include
templates into debug mode e.g.
<## template language="C#" debug="true" hostspecific="true"#>
Popped open %TEMP% to look at the generated file(s) (most recently
modified) just after getting the compiling transformation error.
Searched for the missing / doubled up assembly / class(es) used.
Found which "included" templates both had same reference e.g.
<## include file="MyHelperTemplate.ttinclude" #>
and :
<## include file="EF.Utility.CS.ttinclude" #>
Opened the include folder for the non custom include that was
causing the conflict with my own
..\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\Templates\Includes
Opened this file up, removed its troublesome import
<## import namespace="EnvDTE" #>
Saved it with a new name in same folder and updated references to point to this new version e.g.
<## include file="EF.Utility.CS.Custom.ttinclude" #>
Put required imports into the "parent" templates, and removed from
the "include" template. In my case this was:
<## import namespace="EnvDTE" #>
Now it runs fine, no problems at all, no duplicated imports, and all required assemblies referenced correctly.
Am sure there is a much more sophisticated way of dealing with T4 code reuse which negates this problem entirely. I initially tried importing my own custom assembly, with helpers for the templates, but had what seems like a classic problem with locked dlls when I then tried to build my custom class library.
Seems T4 Toolbox has a solution to this with the VolatileAssembly Custom Directive, and is popular, but looks a bit overkill for my fairly simple needs. Maybe when I have more time.
Hi
If I write a custom package with nothing but static SQL in it, would it invalidate other package. (other third party packages that were shipped as wrapped code).
a co worker suggests that I re write the custom package in Dynamic SQL, and I will not see this problem. I find this hard to believe because the third party packages are not dependent on my custom package,
a compiled package should stay compiled, regardless.
-thank you
It would only invalidate packages that included your custom package as a dependency.
You should be able to prove that to your co-worker (and yourself) in a test environment.
Compiling a new package won't invalidate anything. By definition, an existing compiled package can't refer to your new package that you haven't created yet.
Recompiling an existing package (that might have some references to it) could invalidate existing packages, of course.
No. A package with DML statements would not invalidate any package at all.
When I go to run the t4 templates, the result comes out "Compiling transformation: The name 'TableSpaceName' does not exist in the current context" -- any ideas on this? I thought it might be a namespace/reference issue, but it doesn't seem to be part of the ODP.
This is one of those "it has to be something stupid" ... why? I've got subsonic 2 to work with oracle on the same box, using the same server, same connection string so it has to be something I'm overlooking or not expecting.
I have downloaded the oracle template provider example and I've hit github for the latest and greatest, trying various combinations of both with the results being the same.
In your T4 template, check if you have imported the assembly that includes the missing 'TableSpaceName':
<## assembly name="[ABSOLUTE-PATH-TO-ASSEMBLY]\[ASSEMLBYNAME]" #>