如何识别C#

时间:2015-07-10 09:38:52

标签: c# sql stored-procedures ado.net

我有一个C#方法来执行SQL作业。它成功执行SQL作业。 代码工作得很完美。

我正在使用标准SQL存储过程msdb.dbo.sp_start_job

这是我的代码..

public int ExcecuteNonquery()
{
     var result = 0;
     using (var execJob =new SqlCommand())
     {
          execJob.CommandType = CommandType.StoredProcedure;
          execJob.CommandText = "msdb.dbo.sp_start_job";
          execJob.Parameters.AddWithValue("@job_name", "myjobname");
          using (_sqlConnection)
          {
               if (_sqlConnection.State == ConnectionState.Closed) 
                  _sqlConnection.Open();

               sqlCommand.Connection = _sqlConnection;
               result = sqlCommand.ExecuteNonQuery();

               if (_sqlConnection.State == ConnectionState.Open) 
                 _sqlConnection.Close();
          }
     }
     return result;
}

这是在作业中执行的sp

ALTER PROCEDURE [Area1].[Transformation]
              AS 
              BEGIN
              SET NOCOUNT ON;

              SELECT NEXT VALUE FOR SQ_COMMON
              -- Transform Master Data
              exec [dbo].[sp_Transform_Address];
              exec [dbo].[sp_Transform_Location];
              exec [dbo].[sp_Transform_Product];
              exec [dbo].[sp_Transform_Supplier];
              exec [dbo].[sp_Transform_SupplierLocation];

              -- Generate Hierarchies and Product References
              exec [dbo].[sp_Generate_HierarchyObject] 'Area1',FGDemand,1;
              exec [dbo].[sp_Generate_HierarchyObject] 'Area1',RMDemand,2;
              exec [dbo].[sp_Generate_Hierarchy] 'Area1',FGDemand,1;
              exec [dbo].[sp_Generate_Hierarchy] 'Area1',RMDemand,2;
              exec [dbo].[sp_Generate_ProductReference] 'Area1',FGDemand,1;
              exec [dbo].[sp_Generate_ProductReference] 'Area1',RMDemand,2;

              -- Transform Demand Allocation BOM 
              exec [Area1].[sp_Transform_FGDemand];
              exec [Area1].[sp_Transform_FGAllocation];
              exec [Area1].[sp_Transform_RMDemand];
              exec [Area1].[sp_Transform_RMAllocation];
              exec [Area1].[sp_Transform_BOM];
              exec [Area1].[sp_Transform_RMDemand_FK];

              -- Transform Purchasing Document Data
              exec [dbo].[sp_Transform_PurchasingDoc];
              exec [dbo].[sp_Transform_PurchasingItem];
              exec [dbo].[sp_Transform_ScheduleLine];


              exec [dbo].[sp_CalculateRequirement] 'Area1'
              exec [dbo].[sp_Create_TransformationSummary] 'Area1'
              -- Trauncate Integration Tables 
              exec [dbo].[sp_TruncateIntegrationTables] 'Area1'

              END

问题是,即使作业成功执行,也总是返回 -1 。如何识别作业是否成功执行。

3 个答案:

答案 0 :(得分:3)

MSDN关于SqlCommand.ExecuteNonQuery方法:

  

对于UPDATE,INSERT和DELETE语句,返回值是受命令影响的行数。当插入或更新的表上存在触发器时,返回值包括插入或更新操作影响的行数以及受触发器或触发器影响的行数。对于所有其他类型的语句,返回值为-1。如果发生回滚,则返回值也为-1。

在这一行:

result = sqlCommand.ExecuteNonQuery();

您希望返回受命令影响的行数并将其保存到int变量,但由于语句类型为select所以它返回-1。如果您使用INSERTDELETEUPDATE语句进行测试,您将获得正确的结果。

顺便说一下,如果你想获得受SELECT命令影响的行数并将其保存到int变量,你可以尝试这样的事情:

select count(*) from jobs where myjobname = @myjobname

然后使用ExecuteScalar来获得正确的结果:

result = (int)execJob.ExecuteScalar();

答案 1 :(得分:1)

运行msdb.dbo.sp_start_job后,返回代码将映射到输出参数。您可以在执行前控制参数的名称​​

public int StartMyJob( string connectionString )
{
 using (var sqlConnection = new SqlConnection( connectionString ) )
 {
   sqlConnection.Open( );
   using (var execJob = sqlConnection.CreateCommand( ) )
   {
      execJob.CommandType = CommandType.StoredProcedure;
      execJob.CommandText = "msdb.dbo.sp_start_job";
      execJob.Parameters.AddWithValue("@job_name", "myjobname");
      execJob.Parameters.Add( "@results", SqlDbType.Int ).Direction = ParameterDirection.ReturnValue;      
      execJob.ExecuteNonQuery();
      return ( int ) sqlCommand.Parameters["results"].Value;
    }
  }
}

您需要知道返回代码的数据类型才能执行此操作 - 对于sp_start_job,它需要SqlDbType.Int

但是,这只是启动工作的结果,值得了解,但运行您的工作的结果。要获得作业运行的结果,您可以定期执行:

msdb.dbo.sp_help_job @jobName

该程序返回的一个列是last_run_outcome,可能包含您真正感兴趣的内容。当它仍在运行时,它将是5(未知)。

作业通常是许多步骤 - 根据前面步骤的结果,每个步骤可能会也可能不会执行。另一个名为sp_help_jobhistory的过程支持大量过滤器,以指定您感兴趣的作业的特定调用和/或步骤。

SQL喜欢将工作视为计划工作 - 但是没有什么可以阻止您临时开始工作 - 尽管它并没有真正为您提供大量支持来关联您的广告 - 具有实例的临时作业是作业历史。日期和它一样好(除非有人知道我不知道的伎俩。)

我已经看到作业在运行之前创建 ad-hoc作业的位置,因此当前的临时执行是唯一返回的执行。但是你最终会遇到许多重复或接近重复的工作,这些工作永远不会再被执行。如果你走那条路,你必须计划事后清理的东西。

关于您使用_sqlConnection变量的说明。你不想这样做。你的代码处理它,但它显然是在调用此方法之前在别处创建的。那个糟糕的juju。您最好只创建连接并以相同的方法处理它。依靠SQL连接池来快速建立连接 - 这可能已经开启了。

另外 - 在您发布的代码中 - 看起来您开始使用execJob但是切换到sqlCommand - 并且有点混乱编辑。我认为你的意思是execJob一直贯穿其中 - 而这反映在这个例子中。

答案 2 :(得分:1)

您需要运行存储的进程msdb.dbo.sp_help_job

     private int CheckAgentJob(string connectionString, string jobName) {
        SqlConnection dbConnection = new SqlConnection(connectionString);
        SqlCommand command = new SqlCommand();
        command.CommandType = System.Data.CommandType.StoredProcedure;
        command.CommandText = "msdb.dbo.sp_help_job";
        command.Parameters.AddWithValue("@job_name", jobName);
        command.Connection = dbConnection;
        using (dbConnection)
        {
            dbConnection.Open();      
            using (command){
                SqlDataReader reader = command.ExecuteReader();
                reader.Read();
                int status = reader.GetInt32(21); // Row 19 = Date Row 20 = Time 21 = Last_run_outcome
                reader.Close();
                return status;
            }
        }
     }

enum JobState { Failed = 0, Succeeded = 1, Retry = 2, Cancelled = 3, Unknown = 5};

继续查看未知,直到您得到答案。让我们希望它成功: - )