2016-07-04 21 views
-1

C#でExecuteNonQueryを実装しようとしています。 SQLで実行すると、storedProcedure自体が正常に動作しています。 SubmissionIdのGUIDとSubmitSequenceのテキスト「submit sequence」を返します。しかし、.NETで、それはSubmitSequenceexecutenonqueryから切り捨てられた出力パラメータ

ALTER PROC [dbo].[test_SP] 
(
    @FormId uniqueidentifier, 
    @FormCode varchar(10), 
    @FormTitle nvarchar(200), 
    @User nvarchar(50), 
    @Url nvarchar(255) = NULL, 
    @Host nvarchar(50), 
    @RemoteHost nvarchar(50) = NULL, 
    @UserAgent nvarchar(255) = NULL, 
    @Referrer nvarchar(255) = NULL, 
    @SubmissionId uniqueidentifier out, 
    @SubmitSequence varchar(30) out 
) AS 

BEGIN 

SET @SubmissionId = newid(); 
set @SubmitSequence = 'submit sequence' 

-- INSERT Query 
SELECT 
    @SubmissionId as SubmissionId, @SubmitSequence as SubmitSequence 
END 

のための出力として一つの文字を返すだが.NETで、私は(正しい)SubmissionIdためのGUIDとテキスト「S」SubmitSequenceのために取得しています。

public SubmissionHeaderDTO GetRefNo() 
     { 
      var inPrms = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase) 
          { 
           {"FormId", Guid.NewGuid()}, 
           {"FormCode", "TST"}, 
           {"FormTitle", "Test form"}, 
           {"User", "test"}, 
           {"Host", "iisserver"}        
          }; 
      var outPrms = new Dictionary<string, object>(StringComparer.InvariantCultureIgnoreCase) { 
          { "SubmissionId", Guid.NewGuid() }, 
          { "SubmitSequence", "two"} 
          }; 
      var result = DBHelper.ExecSP(Constants.SPNames.SubmissionHeaderInsert, inPrms, outPrms); 
      SubmissionHeaderDTO refNo = DictionaryToObject<SubmissionHeaderDTO>(result); 
      return refNo; 
     } 

DBHelper.cs

public static Dictionary<string, object> ExecSP(string sp, Dictionary<string, object> paramIn, Dictionary<string, object> paramOut) 
     { 
      var dbAccess = new DBAccess(); 
      var results = dbAccess.ExecuteQuery(sp, paramIn, paramOut); 
      return results; 
     } 

DBAccess.cs

public class DBAccess 
    { 
     public Dictionary<string, object> ExecuteQuery(string storedProcedure, Dictionary<string, object> parameters, 
              Dictionary<string, object> outParameters) 
     { 

      using (var sqlConn = new SqlConnection(Configuration.DBConnection)) 
      { 
       sqlConn.Open(); 
       using(var transaction = sqlConn.BeginTransaction("Results")) 
       { 
        using(var sqlcmd = new SqlCommand(storedProcedure, sqlConn, transaction)) 
        { 
         sqlcmd.CommandType = CommandType.StoredProcedure; 
         foreach(var kv in parameters) 
         { 
          sqlcmd.Parameters.AddWithValue(kv.Key, kv.Value); 
         } 
         foreach(var kv in outParameters) 
         { 
          sqlcmd.Parameters.AddWithValue(kv.Key, kv.Value).Direction = ParameterDirection.Output; 
         } 

         try 
         { 
          sqlcmd.ExecuteNonQuery(); 
          var result = GetOutputParameters(sqlcmd.Parameters); 
          transaction.Commit(); 
          return result; 
         } 
         catch(Exception) 
         { 
          transaction.Rollback(); 
          throw; 
         } 
        } 
       } 
      } 

     } 

     private Dictionary<string, object> GetOutputParameters(SqlParameterCollection paramCollection) 
     { 
      var returnParameters = new Dictionary<string, object>(); 
      foreach (SqlParameter par in paramCollection) 
      { 
       if ((par.Direction == ParameterDirection.Output) || (par.Direction == ParameterDirection.ReturnValue)) 
       { 
        returnParameters.Add(par.ParameterName, par.Value); 
       } 
      } 
      return returnParameters; 
     } 
    } 
+0

出力paramsをプロシージャの結果セットの一部であるために仮定されていない - あなたがすべきではない 'SELECT'ingそれら。 'SET'文はそのままにしておき、' SELECT'文を削除して違いがあるかどうか確認してください。 – Crowcoder

+0

いいえ、違いはありませんでした。私はちょうどSETステートメントを残しました。 Submission Sequenceの出力パラメータ値は、最初の文字にすぎません。 – Rama

答えて

1

私は自分のソリューションにあなたのコードを入れて、問題を再作成。あなたは実際には決してしない理由の一つに就いていますAddWithValue。汎用のobjectを追加するので、sqlパラメータがどのデータ型であるべきかを推測する方法はありません。 ExecuteNonQueryの前に壊れて、パラメータリストを調べると、長さのないNVARCHARと定義されています。したがって、既定では長さは1です。 SqlDbTypeのSQLパラメータを構築する必要があります。AddWithValueの代わりにValueプロパティを設定する必要があります。

この時のパラメータメタデータの外観を問い合わせる動的に開始するにはUPDATE

。それでもSqlDbTypeにSQL型のマッピングのように、行うにはより多くの仕事を持っている注意:

DECLARE @spName sysname; 
SET @spName = 'test_SP'; 

DECLARE @objId int; 
SELECT @objId = ISNULL([object_id], 0) FROM sys.procedures WHERE [name] = @spName; 

SELECT p.[name], p.[system_type_id], t.[name], p.[max_length], p.[precision], 
    p.[scale], p.[is_output], p.[is_nullable] 
FROM sys.parameters p 
INNER JOIN sys.systypes t 
    ON p.[system_type_id] = t.[xtype] 
WHERE [object_id] = @objId; 

enter image description here

+0

私の場合、汎用オブジェクトを使用する必要があります。 AddWithValueを使用せずに私のケースでSqlDbTypeと長さで 'Add'を使う方法を教えてください。 – Rama

+0

'sys.parameters'ビューをクエリして、実行時にストアドプロシージャのパラメータメタデータを調べることができます。 – Crowcoder

+0

NVarcharを除くすべての出力パラメータを返します。誰もsqqbtype = nvarcharとparameterdirection = outputのパラメータを抽出し、そのパラメータのサイズを100に設定するlinqを書いてください。それは私の目的を解決します – Rama

関連する問題