tags:

views:

346

answers:

1

I feel like a dork just for asking this, but I'm not getting any help from Google, and I paged through all of SO's results on a simple search for SMO and didn't see it either.

The short version is that I'm starting to play around with T4. I'm expanding on Oleg Sych's initial tutorial to provide enumeration over all tables to create a (IMHO rather silly) delete proc. This is just an experiment, so its utter uselessness doesn't bother me. :)

My expansion to Oleg's tutorial looks like this:

<#@ template language="C#" hostspecific="true" #>
<#@ output extension="SQL" #>
<#@ assembly name="Microsoft.SqlServer.ConnectionInfo" #>
<#@ assembly name="Microsoft.SqlServer.Smo" #>
<#@ import namespace="Microsoft.SqlServer.Management.Smo" #>
<#@ include file="T4Toolbox.tt" #>
<#
    // Config variables
    string serverName = "dbserver\\dbinstance";
    string dbName = "dbname";
#>
USE <#= dbName #>
<#  
    // Iterate over tables and generate procs
    Server server = new Server(serverName);
    Database database = new Database(server, dbName);

    WriteLine("/* Number of tables: " + database.Tables.Count.ToString() + " */");

    foreach (Table table in database.Tables)
    {
        table.Refresh();
#>
CREATE PROCEDURE <#= table.Name #>_Delete
<#
     PushIndent("    ");
     foreach (Column column in table.Columns)
     {
      if (column.InPrimaryKey)
       WriteLine("@" + column.Name + " " + column.DataType.Name);
     }
     PopIndent();
#>
AS
    DELETE FROM 
        <#= table.Name #>
    WHERE
<#
     PushIndent("        ");
     foreach (Column column in table.Columns)
     {
      if (column.InPrimaryKey)
       WriteLine(column.Name + " = @" + column.Name);
     }
     PopIndent();
     WriteLine("GO");
    }
#>

The issue is that no tables are returned from the Tables collection. This is validated by the table count SQL comment I'm generating, which outputs 0.

As written, the code above generates the following:

USE dbname
/* Number of tables: 0 */

However, if I remove the for loop and manually supply a valid table name which exists in this database, it generates the (again silly) proc -- for that table.

The tables are separated into a schema, would that matter? Also, this is going against a SQL2005 instance -- would that potentially cause issues?

Finally, I'm also finding that I can't enumerate synonyms via the Synonyms collection. (I thought I'd be clever and go that route since the tables are in a schema, but have synonyms defined. But ... no dice.)

Again, to reiterate, the above code is naturally not production, nor even production worthy. I'm just trying to learn both T4 and SMO, and hit a roadblock trying to do something which I'd thought would be ridiculously simple. :)

+2  A: 

SMO does not retrieve metadata automatically if you simply create a new instance of the Database class. Retrieving metadata can take a while, especially in a cold environment. Call database.Refresh() before the loop.

Thanks for the advice! I'm certain it will work, but I'll be sure and update (and accept this) if it doesn't!
John Rudy
You rock. Absolutely worked like a charm. Thanks again!
John Rudy