0

私はC#で初心者で、この割り当てがあります。その一部は、機能を機能させることです。エラーは発生していませんが、実行中に応答もありません。私のコードを見て、「お金」をテキスト ボックスとメッセージ ボックスに表示する方法を教えてください。

private void button2_Click(object sender, EventArgs e)
    {
       SqlConnection conn = Database.GetConnection();

       SqlDataReader rdr = null;

       using (SqlConnection a = Database.GetConnection())
       using (SqlCommand cmd = new SqlCommand("SELECT CalcRentalCharge", a))
            cmd.CommandType = CommandType.StoredProcedure;
            string CarRentalNo = "1";
       try
       {
            conn.Open();

            SqlCommand cmd = new SqlCommand(
            "CalcRentalCharge", conn);

            cmd.CommandType = CommandType.StoredProcedure;

            cmd.Parameters.Add(
            new SqlParameter("@RentalStartDateTime", RentalStartDateTimeBox.Text));
            cmd.Parameters.Add(
            new SqlParameter("@RentalEndDateTime", RentalEndDateTimeBox.Text));
            cmd.Parameters.Add(
                new SqlParameter("@CarTypeID", CarTypeID.Text));
            rdr = cmd.ExecuteReader();


            while (rdr.Read())
            {
                RentalChargeBox.Text = rdr["@Money"].ToString();                      

                MessageBox.Show("@Money");

            }}

        catch
        {
            if (conn != null)
            {
                conn.Close();
            }
            if (rdr != null)
            {
                rdr.Close();
            }
        }   
    }

ストアド プロシージャは次のようになります。

USE [CarRental_P117365]
GO
/****** Object:  UserDefinedFunction [dbo].[CalcRentalCharge]    Script Date:         8/15/2013 09:06:09 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER OFF
GO

/* Create Function CalcFinanceMonthlyPayment to calculate finance monthly repayment */
ALTER FUNCTION [dbo].[CalcRentalCharge] (
@CarTypeID              INT,
@RentalStartDateTime    DATETIME,
@RentalEndDateTime      DATETIME) RETURNS MONEY   

AS
   BEGIN
    DECLARE @NumDays        INT
    DECLARE @DailyRate      MONEY

IF (IsNull(@CarTypeID, 0) <= 0) OR (@RentalStartDateTime IS NULL) OR     (@RentalEndDateTime IS NULL) OR (@RentalEndDateTime <= @RentalStartDateTime)
    RETURN 0

SELECT @DailyRate = DailyRate FROM CarType WHERE CarTypeID = @CarTypeID
IF (IsNull(@DailyRate, 0) <= 0)
    RETURN 0

SELECT @NumDays = CEILING(DATEDIFF(mi, @RentalStartDateTime, @RentalEndDateTime)/ 1440.00)
RETURN CONVERT(MONEY, @NumDays * @DailyRate)
END
4

2 に答える 2

1

コードの致命的ではあるが明らかな欠陥を指摘する価値があるかもしれません。あなたのストアド プロシージャはストアド プロシージャではありません。実際には user defined を表示していますFUNCTION。これは、SP のように呼び出されたときに失敗するのは完全に理にかなっています。エラーが発生しない理由はcatch、C# 側にブロックがあり、エラーについては何もせず、飲み込んで隠すだけであり、C# では禁止されているためです。問題は技術的な問題というよりも設計上の問題のように見えるため、これを解決するためのさまざまなアプローチを考えることができます。

まず、他のことを行う前に、C# 側で適切なエラー処理を行っていることを確認してください。あなたのcatchブロックは、少なくとも失敗した理由の手がかりを与え、エラーをどこかに記録し、メッセージなどを表示する必要がありますtry/catch。エラーであり、サイレント障害ではありません。

さて、実際の問題です。SQL 側でFUNCTIONは、入力パラメーターに対していくつかの計算を行い、DB からデータを取得してさらに計算を実行します。一般的に言えば、関数内のデータ アクセスは良い考えではありませんが、クライアント側から呼び出すことになるため、それほど害はありません。ところで、この関数を、この質問の範囲外の他のクエリ/ストアド プロシージャ/ビューなどの一部として呼び出していますか? そうでなければ、本当のSPになる価値があるかもしれません。

FUNCTIONs はクエリの一部としてのみ呼び出すことができるため、これをクライアント側から直接呼び出すには、クエリを送信する必要があります。これは、おそらくダミー ステートメントでこれを呼び出すだけですSELECT。おそらく、これがFUNCTION今のままで使用する最も簡単な方法です。これは、C# 側の一部を変更することで実行できます。

private void button2_Click(object sender, EventArgs e)
{
   try
   {
       using (SqlConnection connection = Database.GetConnection())
       {
           using (SqlCommand cmd = new SqlCommand("SELECT dbo.CalcRentalCharge(@RentalStartDateTime,@RentalEndDateTime,@CarTypeID)", connection))
           {
               cmd.CommandType = CommandType.Text;
               cmd.Parameters.Add("@RentalStartDateTime", SqlDbType.DateTime).Value = RentalStartDateTimeBox.Text;
               cmd.Parameters.Add("@RentalEndDateTime", SqlDbType.DateTime).Value =  RentalEndDateTimeBox.Text;
               cmd.Parameters.Add("@CarTypeID", SqlDbType.Int).Value = CarTypeID.Text;

               connection.Open();
               decimal rentalChange = (decimal)cmd.ExecuteScalar();
               connection.Close();

               MessageBox.Show("The rental change is: " + rentalChange.ToString());
           }
       }
   }
   catch(Exception ex)
   {
       MessageBox.Show(ex.ToString());
   }
}
于 2013-08-16T00:42:23.763 に答える
0

いくつかのポイント:

パラメータの型が一致しない可能性があります。ストアド プロシージャは 2 つの DATETIME パラメータを取得しますが、実際には文字列を渡します。したがって、2 つの DATETIME パラメータを次のように修正する必要があります。

cmd.Parameters.Add(new SqlParameter("@RentalStartDateTime", SqlDbType.DateTime)
{
   Value = DateTime.Parse(RentalStartDateTimeBox.Text)
});

ストアド プロシージャに出力パラメーターがあることを示す必要があります (パラメーターのリストに追加します)。

@retVal MONEY output

実際に正しい値を返す必要があるため、proc (最終部分) を次のように変更する必要があります。

SET @retVal = CONVERT(MONEY, @NumDays * @DailyRate)
RETURN @retVal

受け取りたい戻り値があることを示す必要があるため、「rdr = cmd.ExecuteReader();」の行から始まるコード 次のように変更する必要があります。

SqlParameter retval = cmd.Parameters.Add("@retVal", SqlDbType.Money);
retval.Direction = ParameterDirection.ReturnValue;
cmd.ExecuteNonQuery();
double retunvalue = (double) cmd.Parameters["@retval"].Value;

また、(a) リーダーを使用する必要がないこと、(b) ストアド プロシージャの呼び出しは非クエリ操作である (およびリーダー操作ではない) ことに注意してください。

于 2013-08-15T08:57:29.430 に答える