6

Estoy haciendo trabajos en cola y al final de cada trabajo quiero activar un SP que procesará mucho los datos. Así que no quiero esperar para completar el SP y solo quiero pasar al siguiente trabajo inmediatamente después de activar el SP. El procedimiento almacenado tomará una entrada del código de activación.Fire and Forget Sql Server Stored Procedure from C#

Problema: -
Este es mi script para crear trabajo. Tenga en cuenta que no le he agregado ningún horario.

BEGIN TRANSACTION 
DECLARE @ReturnCode INT 
SELECT @ReturnCode = 0 
IF NOT EXISTS (SELECT name FROM msdb.dbo.syscategories WHERE name=N'[Uncategorized (Local)]' AND category_class=1) 
BEGIN 
EXEC @ReturnCode = msdb.dbo.sp_add_category @class=N'JOB', @type=N'LOCAL', @name=N'[Uncategorized (Local)]' 
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback 

END 

DECLARE @jobId BINARY(16) 
EXEC @ReturnCode = msdb.dbo.sp_add_job @job_name=N'job_JobName', 
     @enabled=1, 
     @notify_level_eventlog=0, 
     @notify_level_email=0, 
     @notify_level_netsend=0, 
     @notify_level_page=0, 
     @delete_level=0, 
     @description=N'No description available.', 
     @category_name=N'[Uncategorized (Local)]', 
     @owner_login_name=N'UserName', @job_id = @jobId OUTPUT 

IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback 
EXEC @ReturnCode = msdb.dbo.sp_add_jobstep @[email protected], @step_name=N'StepName', 
     @step_id=1, 
     @cmdexec_success_code=0, 
     @on_success_action=1, 
     @on_success_step_id=0, 
     @on_fail_action=2, 
     @on_fail_step_id=0, 
     @retry_attempts=0, 
     @retry_interval=0, 
     @os_run_priority=0, @subsystem=N'TSQL', 
     @command=N'exec dbo.SpToExecute', 
     @database_name=N'DataBaseName', 
     @flags=0 
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback 
EXEC @ReturnCode = msdb.dbo.sp_update_job @job_id = @jobId, @start_step_id = 1 
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback 
EXEC @ReturnCode = msdb.dbo.sp_add_jobserver @job_id = @jobId, @server_name = N'(local)' 
IF (@@ERROR <> 0 OR @ReturnCode <> 0) GOTO QuitWithRollback 
COMMIT TRANSACTION 
GOTO EndSave 
QuitWithRollback: 
    IF (@@TRANCOUNT > 0) ROLLBACK TRANSACTION 
EndSave: 

Ahora cuando comienzo este trabajo mediante la ejecución de EXEC msdb.dbo.job_JobName', que es no ejecutar dbo.SpToExecute. Necesito ejecutar dbo.SpToExecute solo una vez dentro del trabajo y luego el trabajo debe detenerse. De nuevo, cuando ejecuto EXEC msdb.dbo.job_JobName', nuevamente debería ejecutar exec dbo.SpToExecute solo una vez. ¿Puedes decirme cómo lograr esto o lo que me falta aquí?

+2

Tome un vistazo a [SqlCommand.BeginExecuteNonQuery] (http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.beginexecutenonquery.aspx) [SqlCommand.BeginExecuteReader] (http://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.beginexecutereader.aspx) [SqlCommand.BeginExecuteXmlReader] (http://msdn.microsoft.com/en-us /library/system.data.sqlclient.sqlcommand.beginexecutexmlreader.aspx) –

+0

Necesita ejecutarlo en un hilo diferente – nemke

+0

Algún otro subproceso tendrá que esperar el resultado ¿no? Eso no es fuego y olvídate, supongo. Como tengo muchos trabajos en cola, la mayoría de los hilos estarán en uso en algunos de esos trabajos, así que quiero liberar este hilo de acabado rápidamente, después de asignar SQL Server (que reside en otro recuadro) es tarea, hacerlo disponible para uno de los trabajos en la cola. – IsmailS

Respuesta

10

Puede usar el BeginExecuteNonQuery u otros métodos asíncronos o puede crear un trabajo SQL que ejecutará su SP (s) y luego simplemente invocar el ExecuteNonQuery síncrono regular para iniciar el trabajo. Volverá inmediatamente, ya que comenzar un trabajo es rápido. Luego, el trabajo se ejecuta y puede "olvidarse" de eso.

Aquí hay algunos códigos de activación y olvido para el enfoque de trabajo del agente SQL.

string sql = "EXEC dbo.sp_start_job 'THE NAME OF YOUR JOB'";

Y luego sólo hay que ejecutar que en la base de datos. Debería regresar de inmediato. Devolverá un 0 si fue exitoso, y un 1 si no tiene éxito. Ver here.

No se puede pasar un parámetro al trabajo. Entonces, si lo necesita, puede crear una tabla que contenga los parámetros que desea aprobar. Entonces necesitaría actualizar la tabla con los parámetros que desea que su SP use antes de a la que llama sp_start_job SP. Entonces también necesitaría que su SP mirara en esa tabla y vea qué parámetros usar. Es bastante fácil.

Eso es todo. Dispara y olvida.

+0

@Sanjeev: esta es la única respuesta con estas sugerencias, y ningún comentario sugiere el enfoque del trabajo del servidor SQL (que he utilizado con éxito en el pasado). – richard

+0

@Sanjeevakumar ¡No puede hacer un comentario como la respuesta aceptada! – Justin

+0

Correcto, supongo que la compensación entre el comentario y la respuesta es la cantidad de tiempo e interés para una pregunta. Convenido. –

0

Parece que está tratando de manejar todo esto con SQL Server T-SQL y no a través del código .NET.

Si lo que es posible estudiar this implementation

+0

¿Quiere decir que debería implementar todo el proceso de enhebrado (que ya he implementado) nuevamente en T-SQL para este pequeño problema? ;) – IsmailS

0

Lo que se necesita es ASYNCHRONOUS PROCEDURE EXECUTION. Esta solución se basa en Service Broker (link 1, link 2, link 3).

¿Por qué esta solución es mejor?

Remus dice: 10 Agosto 2009 a las 10:06 am No me gusta Agente SQL en estos escenarios por 3 razones:

- que no tiene el mismo balance de carga las capacidades de servicio Activación del intermediario.

- es difícil realizar una copia de seguridad coherente debido a la distribución de metadatos entre la base de datos de usuario y msdb.

- No está disponible en las ediciones Express.

Cuestiones relacionadas