0

一意の ID を使用して追加、更新、削除、および読み取る必要がある Web フォームがあります。これまでのところ、ほとんど問題なく機能を追加、更新、および削除できました。

ただし、現在、読み取り機能を機能させるのに問題があります (ID、FIRSTNAME、SURNAME、および ADDRESS の 4 つのテキスト フィールドを持つ Web フォームがあることを理解してください)。基本的に、(追加ボタンを使用して) 以前に作成された ID がテキスト フィールドに入力され、読み取りボタンがクリックされると、入力された ID に応じて保存されたエントリで他の 3 つのテキスト フィールドが更新されます。

これは、Web フォーム上の私のビハインド コード (cs.) です。

protected void cmdRead_Click(object sender, EventArgs e)
{
   // Create a reference to the Web service
   DbWebService.WebService1 proxy = new DbWebService.WebService1();

   // Create a person details object to send to the Web service.
   string ADDRESS;
   string SURNAME;
   string FIRSTNAME;
   string ID;

   ADDRESS = txtAddress.Text;
   SURNAME = txtSurname.Text;
   FIRSTNAME = txtFirstname.Text;
   ID = txtID.Text;

   // Attempt to store in the Web service
   bool rsp = proxy.ReadPerson(int.Parse(ID), FIRSTNAME, SURNAME, ADDRESS);

   // Inform the user
   if (rsp)
   {
       lblOutcome.Text = "Successfully read data.";

       txtFirstname.Text = FIRSTNAME;
       txtSurname.Text = SURNAME;
       txtAddress.Text = ADDRESS;
   }
   else
   {
       lblOutcome.Text = "Failed to read data! Select a previously created ID!";
   }
}

これが Web サービス上の Web 関数です (ここに SQL Server Express データベースがあります)。

[WebMethod]
public bool ReadPerson(int ID, string FIRSTNAME, string SURNAME, string ADDRESS)
{
   // In case of failure failure first
   bool rtn = false;

   // Connect to the Database
   SqlConnection connection = new SqlConnection(@"Data Source=.\SQLEXPRESS;AttachDbFilename='|DataDirectory|\Database.mdf';Integrated Security=True;User Instance=True");

   // Open the connection
   connection.Open();

   // Prepare an SQL Command
   SqlCommand command = new SqlCommand(String.Format("SELECT FIRSTNAME, SURNAME, ADDRESS FROM PersonalDetails WHERE ID = '{0}'", ID), connection);

   // Execute the SQL command and get a data reader.
   SqlDataReader reader = command.ExecuteReader();

   // Instruct the reader to read the first record.
   if (reader.Read())
   {
      // A record exists, thus the return value is updated
      FIRSTNAME = (string)reader["FIRSTNAME"];
      SURNAME = (string)reader["SURNAME"];
      ADDRESS = (string)reader["ADDRESS"];

      rtn = true;
   }

   // Close the connection
   connection.Close();

   // Return the result.
   return (rtn);

}

ここで問題は、[読み取り] をクリックすると成功メッセージが表示されることです (背後のコードでわかるようにラベルを使用) が、フィールドが更新されません。これは ( rtn = true;) ステートメントが原因であると想定しています。したがって、次のようなものがうまくいくと思いました:

rtn = (bool)reader["ADDRESS"];

ただし、これにより、指定されたキャストが無効になるため、このコンテキストではブール値が機能しない可能性があると考えられます。代わりに文字列を使用すると機能する可能性がありますが、どのように変換すればよいでしょうか。読者に右??

基本的に、Web フォームのテキスト フィールドを更新するソリューションを探しています。

4

1 に答える 1

1

コードにはいくつかの問題があります。最も明白なのは、コードがデータベースからデータを返すことができないということです。FIRSTNAMEあなたはウェブサービスになど送信しています - あなたはそれらウェブサービスから返していません。

boolサービスが成功したかどうかを通知するためにサービスから返される理由はありません。失敗した場合、サービスが例外をスローするようにします。代わりに、サービスのリターンとしてデータベースからフィールドを返す必要があります。

サービス内:

public class Person
{
    public string FIRSTNAME {get;set;}
    public string SURNAME {get;set;}
    public string ADDRESS {get;set;}
}

[WebMethod]        
public Person ReadPerson(int ID)        
{        
    // ...
    if (reader.Read()) 
    { 
        // A record exists, thus return the value
        Person p = new Person();
        p.FIRSTNAME = (string)reader["FIRSTNAME"]; 
        p.SURNAME = (string)reader["SURNAME"]; 
        p.ADDRESS = (string)reader["ADDRESS"]; 

        rtn = p;
   } 

    connection.Close();          

    return rtn; 
}           

また、やむを得ない場合を除き、WebMethod または ASMX Web サービスを使用しないでください。ASMX は、下位互換性のためだけに保持されているレガシー テクノロジです。新規開発には使用しないでください。代わりに WCF を使用する必要があります。


コードに関するその他の問題は、以下で解決されます。

[WebMethod]
public Person ReadPerson(int id)
{
    using (
        var connection =
            new SqlConnection(
                @"Data Source=.\SQLEXPRESS;
        AttachDbFilename='|DataDirectory|\Database.mdf';
        Integrated Security=True;
        User Instance=True")
        )
    {
        connection.Open();

        using (
            var command =
                new SqlCommand(@"
SELECT FIRSTNAME, SURNAME, ADDRESS 
FROM PersonalDetails 
WHERE ID = @id",
                    connection))
        {
            var idParameter =
                command.Parameters.Add(
                    "@id", SqlDbType.Int);
            idParameter.Value = id;

            using (var reader = command.ExecuteReader())
            {
                if (!reader.Read())
                {
                    return null;
                }

                return new Person
                            {
                                Firstname =
                                    (string)
                                    reader["FIRSTNAME"],
                                Surname =
                                    (string)
                                    reader["SURNAME"],
                                Address =
                                    (string)
                                    reader["ADDRESS"]
                            };
            }
        }
    }
}

主な問題はSqlConnection、、、SqlCommandおよびすべてをブロックSqlDataReader内でインスタンス化する必要があることです。usingこれにより、例外がスローされるかどうかにかかわらず、オブジェクトが確実に破棄 (クローズ) されます。

次に、文字列操作によってクエリを作成する習慣を身につけるべきではありません。String.Format を使用していません。これにより、「SQL インジェクション」攻撃を受けやすくなります。パラメータを使用すると、その問題が解決します。MSDN の「コマンドとパラメータ」を参照してください。

最後にもう 1 つ小さな問題があります。明らかなステートメントにコメントを付ける習慣をやめることをお勧めします。たとえばOpen、データベースへの接続を開く、またはreturn値を返す場合は、コメントする必要はありません。

于 2012-04-29T03:42:52.880 に答える