First and foremost: the t4 templates are there for you to change as needed with SS3. That was the main idea with using T4 - I don't want to back you into my silliness :).
To the question at hand - I think this might be a bug in our templates that refuses to stick a value into the PK field:
ISqlQuery BuildInsertQuery(T item) {
ITable tbl = _db.FindTable(typeof(T).Name);
Insert query = null;
if (tbl != null) {
var hashed = item.ToDictionary();
query = new Insert(_db.Provider).Into<T>(tbl); ;
foreach (string key in hashed.Keys) {
IColumn col = tbl.GetColumn(key);
if (!col.IsPrimaryKey) {
query.Value(key, hashed[key]);
}
}
}
return query;
}
In this, our check should actually be...
if (!col.IsPrimaryKey && !col.AutoIncrement) {
query.Value(key, hashed[key]);
}
In this way, the non-identity will be inserted. But in reading your issue here, it sounds to me like you're not trying to insert into a non-identity.
The email you sent me doesn't say anything about PKs as identity - your PK was a thing called "NAme" which is a string type and not and identity (auto-increment).
I'm wondering about when I cannot get around this issue--when I have to add a new record to the database and have an identity as my primary key.
This is what SubSonic assumes - that your PK is an IDENTITY column. If you ONLY have an IDENTITY column, we can't help you because this is a deadlocked table in that you can't insert any value into it, therefor you can't tick the IDENTITY column. Your only recourse at this point is to SET IDENTITY INSERT="off", which defeats the purpose.
Hopefully this will answer your question? If I'm not getting it - can you do this for me:
- One sentence: what can't you do and what's the error
- What did you expect
Thanks Will and I hope I'm not being thick.
Following along with Adam's comment, YOU CAN do this in VS Express, but there are changes required to the template as Adam suggested.
The Visual Studio requirement is only used to get the path to the active project, which is then used to find a web.config file and the app_data path. Since those values are generally known within a project, we can hardcode substitutes values
Update the _Settings.tt file like so:
...
const string ConnectionStringName="Chinook";
//Use this when not building inside visual studio standard or higher
//make sure to include the trailing backslash!
const string ProjectPathDefault="c:\\path\\to\\project\\";
...
public EnvDTE.Project GetCurrentProject() {
if (Host is IServiceProvider)
{
IServiceProvider hostServiceProvider = (IServiceProvider)Host;
if (hostServiceProvider == null)
throw new Exception("Host property returned unexpected value (null)");
EnvDTE.DTE dte = (EnvDTE.DTE)hostServiceProvider.GetService(typeof(EnvDTE.DTE));
if (dte == null)
throw new Exception("Unable to retrieve EnvDTE.DTE");
Array activeSolutionProjects = (Array)dte.ActiveSolutionProjects;
if (activeSolutionProjects == null)
throw new Exception("DTE.ActiveSolutionProjects returned null");
EnvDTE.Project dteProject = (EnvDTE.Project)activeSolutionProjects.GetValue(0);
if (dteProject == null)
throw new Exception("DTE.ActiveSolutionProjects[0] returned null");
return dteProject;
}
return null;
}
...
public string GetConfigPath(){
EnvDTE.Project project = GetCurrentProject();
if (project != null)
{
foreach(EnvDTE.ProjectItem item in project.ProjectItems)
{
// if it is the configuration, then open it up
if(string.Compare(item.Name, "Web.config", true) == 0)
{
System.IO.FileInfo info =
new System.IO.FileInfo(project.FullName);
return info.Directory.FullName + "\\" + item.Name;
}
}
return "";
}
else
{
return ProjectPathDefault+"web.config";
}
}
public string GetDataDirectory(){
EnvDTE.Project project=GetCurrentProject();
if (project != null)
{
return System.IO.Path.GetDirectoryName(project.FileName)+"\\App_Data\\";
}
else
{
return ProjectPathDefault+"App_Data\\";
}
}
...
Then use the VS External Tools feature to set up a T4 tool (Tools->External Tools):
Set these properties:
- Title: T4
- Command: C:\Program Files\Common Files\Microsoft
Shared\TextTemplating\1.2\TextTransform.exe
- Arguments: $(ProjectDir)\Models\Classes.tt
- Initial directory: $(ProjectDir)
- Use Output window and Prompt for arguments should be checked.
Click Ok and then execute the newly created tool from the Tools->External Tools menu.
Best Answer
The SubSonic project has some code examples on their web site (select queries, using active record and stored procedures, for instance. Google also provides a good amount of samples.