3

私は現在、金銭の出入りを追跡するための小さなアプリケーションを作成しています。これは、私の一般的な C# スキルを向上させるためのものです。私のログイン画面には現在、次のコードがあります

    private void Login_Load(object sender, EventArgs e)
    {
        // TODO: This line of code loads data into the 'spendingInsAndOutsDataSet.Users' table. You can move, or remove it, as needed.
        this.usersTableAdapter.Fill(this.spendingInsAndOutsDataSet.Users);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        string userNameText = userName.Text;
        string passwordText = password.Text;

        foreach (DataRow row in spendingInsAndOutsDataSet.Users)
        {
            if (row.ItemArray[4].Equals(userNameText) && row.ItemArray[5].Equals(passwordText))
            {
                MessageBox.Show("Login Successful");

                MainGUI newForm = new MainGUI();
                this.Visible = false;
                newForm.Show();
                break;
            }
            else
            {
                userName.Text = String.Empty;
                password.Text = String.Empty;
                MessageBox.Show("Login Failed");
                break;
            }
        }
    }

ログインが成功したときに実行しようとしているのは、現在の PC の MachineName を SQL データベースの Users テーブルのフィールドに書き込むことです。そうすれば、レコードの作成を開始するときに、UsersId (Transactions テーブルの外部キー) をすばやく見つけることができます。

System.Enviroments パスを使用してアクティブなマシン名を取得できることは知っていますが、更新プログラムを作成する方法が正確にはわかりません。SqlCommand を使用してそれを行う方法は知っていますが、ForEach ループ内で使用した DataRows を使用するより簡単な方法があるかどうか疑問に思っています。

ご不明な点がございましたら、お気軽にお問い合わせください。

ジェームズ

4

2 に答える 2

2

Access データベースであると仮定します (そうでない場合は、必要な変更を行います)。

アダプターを使用して、テーブルに結果を入力します。次に、行の列をユーザーから提供された情報と比較します。データベースを破壊したり、ユーザーの情報をハッカーにさらしたりする可能性のあるインジェクションを避けるために、パラメータを使用することを忘れないでください。

DataTable dt = new DataTable();
String sql = "SELECT * FROM users WHERE user = @user and password=@password"
OleDbConnection connection = getAccessConnection();
OleDbDataAdapter da = new OleDbDataAdapter(sql, connection);
da.SelectCommand.Parameters.Add("@user", OleDbType.VarChar).Value = userNameText;
da.SelectCommand.Parameters.Add("@password", OleDbType.VarChar).Value = password.Text;
try
{
   connection.Open();
   da.Fill(dt);
   connection.Close();
}
catch(OleDbException ex)
{
   connection.Close();
   MessageBox.Show(ex.ToString());
}

if(dt.Rows.Count == 1)
    return true; //username && password matches
else if(dt.Rows.Count == 0)
    return false; // does not match

パラメータに AddWithValue を使用することもできます。

da.SelectCommand.Parameters.AddWithValue("@user", userNameText);

getAccessConnection() は、定義済みの OleDbConnection 関数であり、データベース セットアップへの接続を持ち、接続の新しいインスタンスを作成します (これは私が自分用に作成したものです)。

public OleDbConnection getAccessConnection()
{
    this.connection = new OleDbConnection();
    this.connection.ConnectionString = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" 
            + Classified.SOURCE + ";Jet OLEDB:Database Password=" 
            + Classified.PASS + ";";
    return this.connection;
}

プロジェクトに参加する可能性のある開発者のために、これらすべての機能のクラスを作成することをお勧めします。また、C# テスト駆動開発についてもお読みください。

また、その 1 つのレコードが失敗した場合でも、ループが壊れて、最初のレコードにしか移動できないように見えます。

独自のデータ セットを作成し、それにクエリを実行したテーブルを入力することも役立ちます。以下に簡単な例を示します。

DataSet ds = new DataSet();
ds.Tables.Add(dt, "userSearchedTable");
ds.Tables["userSearchedTable"].Rows[0][1].ToString();

その後、必要に応じて、セット内で特定のデータ テーブルを宣言できます。

于 2013-10-08T21:40:44.103 に答える
2

foreach ループで、現在の PC の MachineName を関連する行に設定し、次にメソッド呼び出しの最後に設定します。

this.usersTableAdapter.Update(this.spendingInsAndOutsDataSet.Users);

これにより、マシン名でデータベースが更新されます

しかし、あなたのコードを見ると、あなたが持っているものを改善するために追加したい追加のコメントがいくつかあります:

データテーブル全体をロードしてから、ユーザー名とパスワードをチェックしています。実際には、データベースでユーザー ID を照会し、その単一の行をロードして、パスワードを確認します。多くのユーザーがいる場合、現在の実装では大量のネットワーク トラフィックが発生します。

それ以外の:

foreach (DataRow row in spendingInsAndOutsDataSet.Users)

次のようなものを使用することを検討してください。

foreach (SpendingInsAndOutsDataSet.UsersRow row in spendingInsAndOutsDataSet.Users)

つまり、データ行オブジェクトの厳密に型指定されたバージョンです。これは、次を使用できることを意味します。

row.Username.Equals(userNameText) 

それ以外の

row.ItemArray[4].Equals(userNameText) 

また、これがネットワーク経由で使用されることが予想される場合は、パスワードの暗号化を検討する必要があります。

于 2013-10-08T21:35:21.090 に答える