2009-08-18 1 views
0

私は.NET 3.5 SP1を使用しています。エンティティフレームワークでストアドプロシージャ@@ ERROR値を取得するには?

私は、以下のようにトランザクションの結果を返すストアドプロシージャを持っている:


Create PROCEDURE SetPrice 
    @itemId int, 
    @price int 
AS 
DECLARE @myERROR int -- Local @@ERROR 
     , @myRowCount int -- Local @@ROWCOUNT 
SET NOCOUNT ON 
BEGIN TRAN1 

UPDATE item_price_table SET [email protected] WHERE [email protected] 
UPDATE order_table SET [email protected] WHERE [email protected] 
SELECT @myERROR = @@ERROR, @myRowCount = @@ROWCOUNT 
IF @myERROR != 0 GOTO HANDLE_ERROR 
COMMIT TRAN1 -- No Errors, so go ahead 
RETURN 0 
HANDLE_ERROR: 
    ROLLBACK TRAN1 
    RETURN @myERROR 

私は@@ ERRORステータスコードが返さ取得しようとしています。 EF v1ので、私はFunctionImport 'SetPrice' を作成し、以下のように 'あるMyContext' クラスのメソッドを作成することによって、それを呼び出した:

The data reader returned by the store data provider does not have enough columns for the query requested. at System.Data.EntityClient.EntityCommandDefinition.ConstantColumnMapGenerator.System.Data.EntityClient.EntityCommandDefinition.IColumnMapGenerator.CreateColumnMap(DbDataReader reader) at System.Data.EntityClient.EntityCommandDefinition.Execute(EntityCommand entityCommand, CommandBehavior behavior) at System.Data.EntityClient.EntityCommand.ExecuteReader(CommandBehavior behavior) at System.Data.EntityClient.EntityCommand.ExecuteScalar[T_Result](Func`2 resultSelector) at System.Data.EntityClient.EntityCommand.ExecuteScalar() 


public int SetPrice(int itemId, int price) {  
Int32 result = -1; 
EntityCommand cmd = ((EntityConnection)this.Connection).CreateCommand(); 
cmd.CommandType = System.Data.CommandType.StoredProcedure; 
cmd.CommandText = "myContext.SetPrice"; 
cmd.Parameters.AddWithValue("itemId", itemId); 
cmd.Parameters.AddWithValue("price", price); 
EntityParameter retParameter = new EntityParameter(); 
retParameter.Direction = System.Data.ParameterDirection.ReturnValue; 
cmd.Parameters.Add(retParameter); 
cmd.Connection.Open(); 
cmd.ExecuteNonQuery(); 
result = Convert.ToInt32(retParameter.Value); 
cmd.Connection.Close(); 
return result; 
} 

これは、次のエラーが発生しました

問題の解決方法を教えてください。

ありがとうございました。

答えて

1

EF v1には、ストアドプロシージャからスカラー値を戻す際に問題があります。 This threadにはさらに詳しい情報があります。

1

長い答えですが、SQL 2005+では@@ ERRORを使用する必要はありません。 SQL Server 2000の場合は、別の方法で使用する必要があります...ストアドプロシージャを使用しているため、WindowsでEntity Frameworkを使用している場合、またはSolarisでjTDSを使用している場合は無関係です...

SQLに欠陥がある)

最初の更新が失敗した場合、これはエラーをトラップしない可能性があります。 @@ ERRORは、最後の文の値を持っています

UPDATE item_price_table SET [email protected] WHERE [email protected] 
UPDATE order_table SET [email protected] WHERE [email protected] 
SELECT @myERROR = @@ERROR, @myRowCount = @@ROWCOUNT 

あなたはすべてのDDL文の後にチェックする必要があります:

UPDATE item_price_table SET [email protected] WHERE [email protected] 
SELECT @myERROR = @@ERROR, @myRowCount = @@ROWCOUNT 
IF @myERROR <> 0 GOTO HANDLE_ERROR 

UPDATE order_table SET [email protected] WHERE [email protected] 
SELECT @myERROR = @@ERROR, @myRowCount = @@ROWCOUNT 
IF @myERROR <> 0 GOTO HANDLE_ERROR 

しかし、これはまだ有効ではありません。その後、再スロー使用してRAISERRORと、クライアントは単に例外を知る必要が起こったことができます。

... 
HANDLE_ERROR: 
    ROLLBACK TRAN1 
    RAISERROR ('Oops: %i', 16, 1, @myERROR) --to pass error number if you really want 

それとも単にSQL Serverの2005+にTRY/CATCHを使用します。キャッチブロック内のRAISERROR

どちらの場合でも、@@ ERRORまたは戻り値を読み取る必要はありません。キャッチされるSQLExceptionに依存しています。私にとっては、ストアドプロシージャは意味のあるデータまたは例外を返します(そして、データは無視されるか無効です)。

PS:なぜ@@ ROWCOUNTを使用しないで保存しますか?

+0

+1確かに@@ ERRORは信じられないほど多くの点で欠陥があります。 –

+0

ありがとうございます。 EF v1でSPサポートを探るサンプルストアドプロシージャを作成しました。 – dev

0

ありがとうございました。その記事で述べたように、SELECT文が必要です。 RETURNの前にSELECTを追加すると、クエリが正しく実行されました。

関連する問題