views:

601

answers:

1

I created a batch file to run SqlMetal and generate Linq2Sql data classes, check into source control triggering a build, etc... I'd like to have this script run anytime there is a DDL change in Sql Server 2005.

Running the batch file via xp_cmdshell works fine outside of a trigger, like this:

exec master..xp_cmdshell 'd:\dev\db_triggers\generatedataclasses.bat', no_output

But when it runs as a trigger, it always times out connecting to the database, causing all DDL to fail. Here's my trigger:

CREATE TRIGGER [Trig_SqlMetal]
ON DATABASE
FOR DDL_DATABASE_LEVEL_EVENTS 
AS
exec master..xp_cmdshell 'd:\dev\db_triggers\generatedataclasses.bat', no_output

I'm looking for advice on two points:

  1. Make this work. For some reason it always fails when in the trigger, and doesn't when not in a trigger. Doesn't appear to be security related since it runs as LocalSystem in both cases.
  2. Make this happen asychronously so that failures and timeouts in SqlMetal don't cause DDL update failure. I've tried wrapping the batch file with another and a "start cmd.exe /c otherbatch.bat", but when running through sql server it seems to ignore the start (works fine from DOS). I could certainly write a polling process to look at some table and pickup events, but I'd prefer this be trigger based to make it less complex (or am I doing the opposite :) ).
+3  A: 

Your batch is probably being blocked because it tries to query data about the tables being created, but they are still locked inside a transaction (the trigger is part of the implicit transaction SQL Server starts for any DDL/DML statement), that will complete only after the trigger finishes. The only "almost" practical way of asynchronous execution in SQL Server 2005 or higher that I know of is Service Broker. Look for "Service Broker Internal Activation". In practice it is a bit complex to set it up properly, so you might well choose to go for the pooling option.

LeoPasta
Excellent point - this is surely why they are locked. Any idea why doing a "start cmd.exe /c bartc.bat" isn't working to get the asynch?
TheSoftwareJedi
Not sure, my (wild) guess is that the both DOS sessions are being opened in the context of the SQL Server process, and SQL is waiting for all its children to close before returning control to the trigger.
LeoPasta