0

問題を引き起こしているのはデータの量であり、データを送信/解析する方法ではない可能性が高いと思います (そして、データを受信するデバイスが 98 ポンドの弱いもの (Windows を実行している古いハンドヘルド デバイス) .NET 1.1)) を使用する CE では、一部のデータの XML 処理を、代わりにダウンする CSV ファイルの解析に変更する任務を負っています。

「問題のある」データは、典型的な XML 料金です。

<PlatypusItems>
    <PlatypusID>DARINTULIP</PlatypusID>
    <PlatypusItemID>010476</PlatypusItemID>
    <ItemID>01820000468</ItemID>
    <BillSize>15</BillSize>
  </PlatypusItems>
  <PlatypusItems>
    <PlatypusID>DARINTULIP</PlatypusID>
    <PlatypusItemID>011065</PlatypusItemID>
    <ItemID>01820000478</ItemID>
    <BillSize>15</BillSize>
  </PlatypusItems>
  <PlatypusItems>
    <PlatypusID>DARINTULIP</PlatypusID>
    <PlatypusItemID>015165</PlatypusItemID>
    <ItemID>01820000481</ItemID>
    <BillSize>15</BillSize>
  </PlatypusItems>
  <PlatypusItems>
    <PlatypusID>DARINTULIP</PlatypusID>
    <PlatypusItemID>010420</PlatypusItemID>
    <ItemID>01820000907</ItemID>
    <BillSize>24</BillSize>
  </PlatypusItems>
(etc.)

これを行う (レガシー - 私は書いていない) コードを調べると、(少なくとも私には) 奇妙に見えることがいくつかあり、データ サイズや解析方法論ではなく、そうなる可能性があるのではないかと考えています。問題の[少なくとも一部である]。

たとえば、次の 2 番目のインスタンスで var dSQL が使用されている理由はありますか? SqlCeCommand の CommandText プロパティと同じですが、params を使用しません。コンテキストに入れるために、かなりのコードを示します。

if (File.Exists(filePathName)) // <-- filePathName contains the name of the XML file to be parsed
{
    DataSet dset = new DataSet("DuckbillSetup");
    dset.ReadXml(filePathName);

    dSQL = "DELETE FROM Platypi";
    try
    {
        dbconn.DBCommand(dSQL, true);
    }
    catch
    {
        //bla [elided/excised]
    }

    SqlCeConnection conn = dbconn.GetConnection();
    if (conn != null && conn.State == ConnectionState.Closed)
    {
        conn.Open();
    }
    SqlCeCommand cmd = conn.CreateCommand();

    cmd.CommandText = "INSERT INTO Platypi ( PlatypusID, PlatypusItemID, ItemID, BillSize) VALUES (?, ?, ?, ?)";

    foreach (DataTable tab in dset.Tables)
    {
        if (tab.TableName.ToLower() == "Platypi".ToLower())
        {
            foreach (DataRow row in tab.Rows)
            {
                PlatypusItem PlatypusItm = new PlatypusItem();
                if (!ret)
                    ret = true;
                foreach (DataColumn column in tab.Columns)
                {
                    if (column.ColumnName == "PlatypusID")
                    {
                        PlatypusItm.PlatypusID = (string) row[column];
                    }
                    else if (column.ColumnName == "PlatypusItemID")
                    {
                        if (!row.IsNull(column))
                            PlatypusItm.PlatypusItemID = (string) row[column];
                        else
                            PlatypusItm.PlatypusItemID = "";
                    }
                    else if (column.ColumnName == "ItemID")
                    {
                        if (!row.IsNull(column))
                            PlatypusItm.ItemID = (string) row[column];
                        else
                            PlatypusItm.ItemID = "";
                    }
                    else if (column.ColumnName == "BillSize")
                    {
                        if (!row.IsNull(column))
                            PlatypusItm.BillSize = Convert.ToInt32((string) row[column]);
                        else
                            PlatypusItm.BillSize = 0;
                    }
                }
                PlatypusItemList.List.Add(PlatypusItm);

                dSQL = "INSERT INTO Platypi (PlatypusID, PlatypusItemID, ItemID, BillSize) VALUES (" + PlatypusItm.PlatypusID + ",'" +
                       PlatypusItm.PlatypusItemID + "','" + PlatypusItm.ItemID + "'," + PlatypusItm.BillSize + ")";

                if (!First)
                {
                    cmd.Parameters[0].Value = PlatypusItm.PlatypusID;
                    cmd.Parameters[1].Value = PlatypusItm.PlatypusItemID;
                    cmd.Parameters[2].Value = PlatypusItm.ItemID;
                    cmd.Parameters[3].Value = PlatypusItm.BillSize.ToString();
                }

                if (First)
                {
                    cmd.Parameters.Add("@PlatypusID", PlatypusItm.PlatypusID);
                    cmd.Parameters.Add("@PlatypusItemID", PlatypusItm.PlatypusItemID);
                    cmd.Parameters.Add("@ItemID", PlatypusItm.ItemID);
                    cmd.Parameters.Add("@BillSize", PlatypusItm.BillSize);
                    cmd.Prepare();
                    First = false;
                }

                if (frmCentral.CancelFetchInvDataInProgress)
                {
                    return false;
                }

                try
                {
                    dbconn.DBCommand(cmd, dSQL, true); // <-- Why dSQL? Why not: dbconn.DBCommand(cmd, cmd.CommandText, true);
                }
            . . .

...私は、問題はコマンドでの dSQL の使用である可能性が高いと考える傾向があります (したがって、問題は XML の解析ではなく、データベースへの挿入であり、"hicc[ough,up]フライスルーするパラメーターを持つのではなく、解明しなければならない SQL ステートメント内のクラス メンバーに直面するたびに)。XML 解析が CSV 解析よりもはるかにパフォーマンスが低い場合、それを高速化する方法はありますか、または CSV ファイルに切り替えることは本当に賢明ですか?

アップデート

XMLファイルの解析/読み取りの直前と直後に、 MessageBox.Show()s をコードに挿入してテストしました(そのようにする必要があります-これらの領域ではすでに長い話が何度もありました)。データを挿入する for ループの前後。確かに、私のテストデータは膨大ではありませんが、どちらの場合も、「開始」メッセージと「終了」メッセージの間の時間は実質的に瞬時でした...クロールまで速度が低下することに興味があります(テスターは、1つに10分かかったと述べましたサイトをロードするのに 30 分かかると推定しました (それを待ちませんでした))。

更新 2

ここから抜粋した以下のコードを適用する方法がよくわかりませんhttp://msdn.microsoft.com/en-us/library/537kf788(v=vs.90).aspx (ErikEJの回答にリンクされています):

cmd.CommandText = "SELECT * FROM myTable";
SqlCeResultSet rs = cmd.ExecuteResultSet(ResultSetOptions.Updatable |
    ResultSetOptions.Scrollable);

SqlCeUpdatableRecord rec = rs.CreateRecord();

// Insert 10 records
//
for (int i = 0; i < 10; i++)
{
    rec.SetInt32(0, i);
    rs.Insert(rec);
}

最初にテーブルからすべてのレコードを読み取ることが本当に必要/賢明ですか? 膨大な数のレコードが含まれている場合はどうなるでしょうか? それとも、実際にはそうしていないのでしょうか?

SetInt32() は何をするのでしょうか? テーブルに更新中の ID 列があると想定しているように見えますが、通常は自動インクリメントされるため、そうではありません。

おそらくrec.SetInt32(0,i)は、次の単なるプレースホルダーです。

rec.MyFirstClassmember(bla);
rec.MySecondClassmember(Blee);
...etc.

しかし、とにかく、「SqlCeResultSet」も「SqlCeUpdatableRecord」も利用できないようです-実際、次のコードでは:

SqlCeResultSet rs = cmd.ExecuteResultSet(ResultSetOptions.Updatable | ResultSetOptions.Scrollable);
SqlCeUpdatableRecord rec = rs.CreateRecord();

...VS2003 コード エディターでは、"res = cmd."、".Updatable |"、".Scrollable"、および "rec = rs." を除くすべてが赤です。

使用可能な「解決」コンテキスト メニュー項目はありません。「using System.Data.SqlServerCe;」があります。このユニットで。

一言で言えば、このアプリの問題点は、昔ながらのサイケデリックなスクリーン セーバーのように、自分自身の周りや下に織り込まれていることです。「スパゲッティ」という言葉は間違いなく頭に浮かびますが、おそらく「卵の殻」という言葉の方が適しているでしょう (ハンプティ・ダンプティを考えてください)。「スパゲッティが卵の殻に変わるのはいつ?」回答: 「不適切に記述されたコードが壊れた場合。」

更新 3

以下のコメントで提供されたリンク ( http://mobilesandbox.blogspot.dk/2009/02/sql-compact-insert-performance.html ) のプロジェクトのコード:

rs = cmd.ExecuteResultSet(ResultSetOptions.Updatable);
rec = rs.CreateRecord();

for(i = 0; i < m_nSampleSize; ++i) 
{
    rec.SetInt32(0, i);
    rs.Insert(rec);
}

...同じレコード (rec) が何度も挿入されているようです。私が間違っている?rs は、毎回結果セット内の次のレコードにインクリメントすることを認識できるほどスマートですか? もしそうなら、なぜ「while not endOfResultSet」ループではないのでしょうか?

4

1 に答える 1

1

確かに遅い応答を引き起こしているのは INSERT ステートメントです。T-SQL を回避し、SQL Server Compact を使用して「生の」テーブルに直接 INSERT を実行する方法があります。MSDN で SqlCeUpdateableRecord および SqlCeResultSet.Insert メソッドを探してください。http://msdn.microsoft.com/en-us/library/537kf788(v=vs.90).aspx

于 2013-05-25T07:35:12.370 に答える