2017-12-28 12 views
-1

WCFからいくつかの行が取得されています。これらを1つずつローカルSQLite DBに挿入します。この目的のために、私はSQLItePCLを使用しています。デバッガを使用して、約900行があることを検出した後、forループを開始し、すべてを1つずつ挿入しました。しかし、それは単一の行を挿入するのではなく、ローダー(データが挿入されているときに表示するためにローダーを使用しています)を無限にロードしています。私はLocalStateフォルダ内の私のローカルDBのサイズをチェックしていますが、何も起こっていないことを意味する増加していませんが、私のアプリもクラッシュしていません。行番号は以下200未満であるとき、すべてがうまくされたデータを挿入するためのコードです:ここに問題がある可能性がありますどのようなSQLitePCLを使用してSQLiteのWCFから900行(巨大な行数)の行を挿入しない

using (SQLiteConnection Conn = new SQLiteConnection("BerriaDb.db")) 
{ 
    List<BerrianWebService.FoodCode> ResponseData = wsResponse.data.ToList(); 
    for (int i = 0; i < ResponseData.Count; i++) 
    { 
     string sqlInsFoodCode = @"INSERT INTO [FoodCode] ([ID], [Item_Name], [Code], [ItemID], [FoodCodeID], [Brief_Descriptor], [Full_Descriptor], [Guidesheet], [REG], [Status], [syncDate]) VALUES (" + ResponseData[i].ID + ", '" + ResponseData[i].Item_Name + "', '" + ResponseData[i].Code + "', '" + ResponseData[i].ItemID + "', '" + ResponseData[i].FoodCodeID + "', '" + ResponseData[i].Brief_Descriptor + "', '" + ResponseData[i].Full_Descriptor + "', '" + ResponseData[i].Guidesheet + "', '" + ResponseData[i].REG + "', '" + ResponseData[i].Status + "', '" + LastSyncDateTime + "')"; 
     using (ISQLiteStatement connStatement = Conn.Prepare(sqlInsFoodCode)) 
     { 
      connStatement.Step(); 
     } 
    } 
} 

?ここでStringBuilderを使うべきですか?なにか提案を?ありがとう

編集:主な問題は、実際には、ResponseDataが大きすぎるとき(900のような)、それぞれが1つの中でループしてその値を評価することができない、 SQLの文字列を構築するが、静的な値を与えているときにうまくいきます。どんな助け?

+1

;' 'VARボブ= connStatement.Step()には;'何行100,199,200,201の 'bob'の値は? – mjwills

+0

「文字列sqlInsFoodCode = ..........」の後にVisual Studioに戻ってこない理由はわかりません:( – Kibria

+0

はい、私はすでに行っていますが、それ以上のことはしません "string sqlInsFoodCode = @ "INSERT INTOコマンドがここに来ますが、私はこれをチェックしました" "、ローダーは無限の時間の読み込みを開始します – Kibria

答えて

0

あなたのコードはSQLインジェクション攻撃のためにオープンされており、SQLステートメントの構築とそれに続くステップ呼び出しが失敗する理由も説明されています。

代わりに、Prepared statementを最大限活用するには、バインドパラメータとそれに対応するBind呼び出しを導入します。次のようにあなたのコードを適応させる:

var LastSyncDateTime = DateTime.Now; 

using (SQLitePCL.SQLiteConnection Conn = new SQLitePCL.SQLiteConnection("BerriaDb.db")) 
{ 

    // use Bind Parameters, that are the @id, @item_name etc 
    string sqlInsFoodCode = @" 
    INSERT INTO [FoodCode] (
     [ID], 
     [Item_Name], 
     [Code], 
     [ItemID], 
     [FoodCodeID], 
     [Brief_Descriptor], 
     [Full_Descriptor], 
     [Guidesheet], 
     [REG], 
     [Status], 
     [syncDate]) 
    VALUES (
     @id, 
     @item_name, 
     @code, 
     @itemid, 
     @foodcodeid, 
     @brief_descriptor, 
     @full_descriptor, 
     @guidesheet, 
     @reg, 
     @status, 
     @lastsynctime)"; 

    // we can now re use this statement for all inserts 
    using (ISQLiteStatement connStatement = Conn.Prepare(sqlInsFoodCode)) 
    { 
     List<FoodCode> ResponseData = wsResponse.data.ToList(); 
     for (int i = 0; i < ResponseData.Count; i++) 
     { 
      // just to be sure no values from last time are kept 
      connStatement.ClearBindings(); 

      // bind the values from the Responsedata to the parameters 
      connStatement.Bind("@id", ResponseData[i].ID); 
      connStatement.Bind("@item_name", ResponseData[i].Item_Name); 
      connStatement.Bind("@code", ResponseData[i].Code); 
      connStatement.Bind("@itemid", ResponseData[i].ItemID); 
      connStatement.Bind("@foodcodeid", ResponseData[i].FoodCodeID); 
      connStatement.Bind("@brief_descriptor", ResponseData[i].Brief_Descriptor); 
      connStatement.Bind("@full_descriptor", ResponseData[i].Full_Descriptor); 
      connStatement.Bind("@guidesheet", ResponseData[i].Guidesheet); 
      connStatement.Bind("@reg", ResponseData[i].REG); 
      connStatement.Bind("@status", ResponseData[i].Status); 
      connStatement.Bind("@lastsynctime", LastSyncDateTime.ToString()); 

      // alwaws take the result ... 
      var result = connStatement.Step(); 
      // ... and check if we're OK, (done in this case) 
      if (result != SQLiteResult.DONE) 
      { 
       // if not, yell at the caller 
       throw new Exception(String.Format("ResponseData[{0}].ID('{1}') not inserted. Result: {2}", i, ResponseData[i].ID, result)); 
      } 
      // enable the re-use of the prepared statement, so call Reset 
      connStatement.Reset();    
     } 
    } 
} 

が100行を挿入

は私の箱の上に約10秒かかり、その時は、それ以上の列のために線形です。

テスト中に":memory:"をデータベース名として使用します。そうすれば、ディスクに書き込むよりもはるかに速いインメモリストアが得られます。ここ

誰もこれにtestrunを与えたい場合は、サポートクラスです:あなたは `connStatement.Step()を変更した場合

// this will be an instance in wsResponse 
class response 
{ public response() { 
     data = Enumerable.Range(1,10).Select(id => new FoodCode(id)).ToArray(); 
    } 
    public FoodCode[] data; 
} 

class FoodCode 
{ 
    public int ID; 
    public string Item_Name; 
    public string Code; 
    public int ItemID; 
    public int FoodCodeID; 
    public string Brief_Descriptor; 
    public string Full_Descriptor; 
    public string Guidesheet; 
    public string REG; 
    public string Status; 

    public FoodCode() 
    { 
     // populate all fields with random stuff 
     foreach(FieldInfo fi in this.GetType().GetFields()) 
     { 
      if (fi.FieldType == typeof(string)) { 
       fi.SetValue(this, GenString(fi.Name, ID)); 
      } else 
      { 
       fi.SetValue(this, rnd.Next(1,255)); 
      } 
     } 
    } 

    public FoodCode(int id):this() 
    { 
     ID = id; 
    } 

    static Random rnd = new Random(); 
    // generate a random string 
    private string GenString(string name, int id) 
    { 
    var result = new string[] { name, id.ToString(), new String(Enumerable.Range(0,5000).Select(_=> (char) rnd.Next(33,127)).ToArray())}; 
    return String.Join("-", result); 
    } 

} 
関連する問題