2016-09-29 5 views
0

J'ai un problème lorsqu'un SqlDataAdapter ne remplit pas un DataTable lors de l'exécution d'une procédure stockée SQL Server particulière, malgré le fait que de nombreuses fonctions similaires exécutent des procédures stockées presque identiques qui fonctionnent toutes correctement.SqlDataAdapter ne remplit pas DataTable

Voici la fonction qui exécute la procédure stockée et renvoie le DataTable rempli;

public DataTable getAssetClassifications(int? pLevel) 
{    
    // Create dataTable to hold data 
    var dt = new DataTable(); 

    // Initialize connection 
    using (connection = new SqlConnection(connectionString)) 
    using (SqlCommand command = connection.CreateCommand()) 
    using (SqlDataAdapter adapter = new SqlDataAdapter(command)) 
    { 
     // Open connection 
     connection.Open(); 

     // Set connection properties 
     command.CommandText = "BR_Manage_Primary_Classification_GetItemsAssets"; 
     command.CommandType = CommandType.StoredProcedure; 

     // Add params 
     command.Parameters.AddWithValue("@pLevel", pLevel); 

     // Create return value parameter 
     SqlParameter returnValue = new SqlParameter(); 
     returnValue.Direction = ParameterDirection.ReturnValue; 

     // Add return value to command 
     command.Parameters.Add(returnValue); 

     // Execute command 
     command.ExecuteNonQuery(); 

     // Fill DataTable 
     adapter.Fill(dt); 

     // Get result 
     var result = returnValue.Value; 

     Console.WriteLine("Get asset classifications result: " + result.ToString()); 

     if (result.Equals(0)) 
     { 
      return dt; 
     } 
    } 

    return null;  
} 

L'exécution de ce avec pLevel = null retournera null où il devrait être de retour un jeu d'enregistrements 382 de ligne. À partir du débogage, je peux voir que 'adapter.fill (dt)' renvoie 382, ​​comme il se doit, et pourtant le DataTable 'dt' n'est pas rempli.

La procédure stockée est présentée ici:

CREATE PROCEDURE BR_Manage_Primary_Classification_GetItemsAssets 
/* 
TODO: Allow for subsets based on tree branches 
*/ 
    @pLevel AS INT = NULL 
AS 
BEGIN 
/*  
    Description: Independently returns asset classifications 

     exec BR_Manage_Primary_Classification_GetItemsAssets 

    Outputs: None 

    NOTE: This BR doesn't write, so it doesn't audit but it does error log the call to the DAL. 

*/ 
    SET xact_abort, nocount on 
    DECLARE @StoredProcedureName AS SYSNAME = quotename(object_schema_name(@@procid))+'.'+quotename(object_name(@@procid)) 
    DECLARE @Parameters AS NVARCHAR(1000) = 'Parameters: ' 
    DECLARE @LocalError AS INT 
    DECLARE @LocalErrorMessage AS NVARCHAR(2048) 
    DECLARE @NewAuditID AS INT = NULL 

BEGIN TRY 
    BEGIN TRANSACTION 
     EXEC DAL_Primary_Classification_GetItemsAssets 
    COMMIT TRANSACTION 

    -- Return SUCCESS 
    RETURN 0 
END TRY 
BEGIN CATCH 
    -- On fail close any open transactions and write to Error Log 
    SET @LocalError = @@ERROR 
    SET @LocalErrorMessage = ERROR_MESSAGE() 

    IF @@trancount > 0 
     ROLLBACK TRANSACTION 

    -- Actual error logging 
    EXEC DAL_System_LogError null, @StoredProcedureName, @LocalError, @LocalErrorMessage, @Parameters, null, null, null 

    -- Return Error 
    RETURN 1 
END CATCH 
END 

Cela appelle le DAL:

CREATE PROCEDURE [dbo].[DAL_Primary_Classification_GetItemsAssets] 
as 
begin 
    /* 
    Description: Returns all assets 

      exec [DAL_Primary_Classification_GetItemsAssets] 

      exec DAL_Primary_Classification_GetItems 3, 4 

    Outputs: None 

*/ 
set nocount on; 

select c.id as rule_id, 
     c.[Description] as rule_description, 
     c.Comment as rule_comment, 
     l91.id as L91_IDm, 
     l91.name as L91_Name, 
     l91.[Description] as L91_Description, 
     l91.Comment as L91_Comment, 
     l92.id as L92_ID, 
     l92.name as L92_Name, 
     l92.[Description] as L92_Description, 
     l92.Comment as L92_Comment 

from Classifications_Assets as c 
      left outer join Class_L9_1 as l91 on c.Class_L9_1_ID = l91.ID  and l91.Deleted = 0 
      left outer join Class_L9_2 as l92 on c.Class_L9_2_ID = l92.ID  and l92.Deleted = 0 
where c.Deleted = 0 
end 

Désolé pour le mur de texte, toute aide serait grandement appréciée!

+0

Avez-vous vérifié la valeur de 'resultValue' dans le débogueur? –

+0

La valeur de résultat renvoie 0 pour le succès qui est bien –

Répondre

0

Dans cette réponse: https://stackoverflow.com/a/14816172/4519548

Le gars ajoute le paramètre un peu différemment. Il passe le SqlDbType.Int à la méthode Add:

SqlParameter returnParameter = cmd.Parameters.Add("RetVal", SqlDbType.Int); 
    returnParameter.Direction = ParameterDirection.ReturnValue; 
    cmd.ExecuteNonQuery(); 

    int id = (int) returnParameter.Value; 

Peut-être que cela vous aide.

1

Je pense que je vous ai mal compris sur mon autre réponse.

Je vois que vous appelez ExecuteNonQuery avant adapter.Fill(dt).

Avez-vous besoin d'appeler ExecuteNonQuery là?

Pouvez-vous tester sans elle?

+0

Oui juste eu un coup d'oeil et il ne fait aucune différence, même si je pense que je pourrais essayer d'utiliser un lecteur pour voir si cela fait une différence –

+0

C'est mauvais ... :( –

+0

Peut-être que le problème est d'appeler un SP qui appelle un autre SP Avez-vous essayé en utilisant un seul SP? Je ne suis pas sûr si vous pouvez récupérer le résultat de l'exec à un exec externe (c'est confus) –