2

このコードは無駄が多く、風変わりで奇妙に思えるので、リファクタリングしたいと思います。

public string getVersion()
{
    try
    {
        string dynSQL = "SELECT * FROM invHeader";
        DataSet workSites = dbconn.getDataSet(dynSQL);

        //Go thru dataset and display the working files
        //Only need one, although we'll be duplicating the version
        //per each site as a check value during upgrades
        //return workSites.Tables[0].Rows
        foreach (DataRow row in workSites.Tables[0].Rows)
        {
            sVersion = row["ID"].ToString();
            break;
        }
    }
    catch (Exception ex)
    {
        Duckbill.ExceptionHandler(ex, "InvHeader.getVersion");
    }

    return sVersion;
} // getVersion

私はそれを次のように変更できると考えていました:

public string getVersion()
{
    try
    {
        string dynSQL = "SELECT FIRST ID FROM invHeader"; // I also tried "SELECT 1 ID FROM invHeader"
        DataSet workSites = dbconn.getDataSet(dynSQL);
        return workSites.Tables[0].Rows[0]["ID"].ToString();
    }
    catch (Exception ex)
    {
        Platypus.ExceptionHandler(ex, "InvHeader.getVersion");
    }
} // getVersion

...しかし、どちらのクエリも必要なものを返しませんでした(最初の行の ID の値)。それで、それを行うためのSQLは何ですか。

ところで、これある種のスカラー呼び出しであることはわかっていますが、相互に依存するこれらの自家製の自己ロール メソッドでは、非常に多くのファンキーな Rube Goldbergesque が発生します。ただし、この小さなクリーンアップは、ブーツで震えることなく実行できるはずです.

アップデート

SQL Server CE クエリ アナライザーで「SELECT TOP 1 ID FROM invHeader」という答えを出す銃を飛ばしたと思います。結果は次のようになります。

FAILED: SELECT TOP 1 ID FROM invHeader 
Error: x800...._E_ERRORSINCOMMAND
Native Error: (25501)
Description: There was an error parsing the query. [Token line number, Token line offset, Token in error,,]
Interface defining error: IID_ICommand
Paaram. 0:1
Param. 1: 8
Param. 2:0
Param. 3: TOP
Param. 4:
Param. 5:

これは非常に不可解に思えますが、私が理解していることの 1 つは、SQL Server CE クエリ アナライザが「面白くない」ということです。

更新 2

私は、この同類のさらにひどいコード臭を発見しました。メソッドの名前から、メソッドが値を返すと思わせるだけではありません (そうです、本当です)。ただし、それを行っている間、最初のレコードを単純に取得するために、潜在的に大きなテーブルからすべてのレコードを取得します (再び)。

これを書いた猫が、「SELECT *」の乱暴な使用法に対するメモ警告を受け取らなかった可能性は本当にありますか?

コード難読化コンテストに匿名で応募できますか?

public string getINVSite()
{
    string  siteStr   = "";
    string  dSQL      = "";
    DataSet workSites;

    dSQL      = "SELECT * FROM inventory";
    dbconn    = DBConnection.GetInstance();
    workSites = dbconn.getDataSet( dSQL );

#if true
//            DataRow row = workSites.Tables[0].Rows[0];

    siteStr = "1";
    if (workSites.Tables.Count > 0)
    {
        if(workSites.Tables[0].Rows.Count>0)
            siteStr = workSites.Tables[0].Rows[0]["ID"].ToString();
    }
    return( siteStr );
#else
    //Go thru dataset and display the working files
    foreach( DataRow row in workSites.Tables[0].Rows )
    {
        return( row["ID"].ToString() );
    }

    return( "" );
#endif
} // getINVSite

今、あなたは私が負担している重荷を知っています。哀れに思うなら、あなたが選んだ慈善団体に寄付してください。

更新 3

申し訳ありません。あなたの助けに感謝しますが、これはウサギの穴が多すぎます。元のコードはマッドハッターにふさわしいものですが、機能します。もっと臭い魚を揚げなければならないので、少なくとも今のところは置いておきます。私はこれを試しました:

public string getVersion()
{
    string conStr = "Data Source = " + dbconn.filename;
    MessageBox.Show(string.Format("conStr in InvHeader.getVersion() is {0}", conStr));//TODO: Remove after testing
    try
    {
        using (SqlCeConnection connection = new SqlCeConnection(conStr))
        {
            connection.Open();
            using (SqlCeCommand command = new SqlCeCommand("SELECT ID FROM invHeader", connection))
            using (SqlCeDataReader reader = command.ExecuteReader())
            {
                if (reader.Read())
                {
                    string s = reader.GetString(0);
                    MessageBox.Show(string.Format("version InvHeader.getVersion() is {0}", s));//TODO: Remove after testing
                    return s;// reader.GetString(0);
                }
                else
                {
                    // no result
                    return null;
                }
            }
        }
    }
    catch (Exception ex)
    {
        Pterodactyl.ExceptionHandler(ex, "InvHeader.getVersion");
        return string.Empty;
    }
}

...それでも例外が発生します。最初の MessageBox.Show() で接続文字列を見た後、2 番目の文字列が表示されません。

4

4 に答える 4

3

DataSet を使用しないでください。これまで。

以下は良い最初のパスです。TableDirect を使用して id フィールドにインデックスを付けると、より高速になる可能性がありますが、最初にこれを実行して、パフォーマンスが許容できるかどうかを確認します。

public string GetVersion()
{
    using (var connection = new SqlCeConnection("my connection string"))
    {
        connection.Open();
        using (var command = new SqlCeCommand("SELECT id FROM invHeader", connection))
        using (var reader = command.ExecuteReader())
        {
            if (reader.Read())
            {
                return reader.GetString(0);
            }
            else
            {
                // no result
                return null;
            }
        }
    }
}
于 2013-09-19T23:09:23.297 に答える
2

DataSet の使用を避け、SqlCommand および ExecuteScalar メソッドを使用します。

編集済み

このコードは、同等で機能的で高速である必要があります。

public string getVersion()
{
    try
    {
        // Use TOP (N) http://technet.microsoft.com/en-us/library/bb686896.aspx
        string dynSQL = "SELECT TOP (1) ID FROM invHeader";
        return (string)(new SqlCeCommand(dynSQL, dbconn.getConnection()).ExecuteScalar());
    }
    catch (Exception ex)
    {
        Platypus.ExceptionHandler(ex, "InvHeader.getVersion");
    }
} // getVersion   

dbconn が、dbconn.getConnection() を呼び出す SqlCeConnection を提供できるクラスであると仮定します。

于 2013-09-19T22:23:12.327 に答える