あなたのコードは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);
}
}
;' 'VARボブ= connStatement.Step()には;'何行100,199,200,201の 'bob'の値は? – mjwills
「文字列sqlInsFoodCode = ..........」の後にVisual Studioに戻ってこない理由はわかりません:( – Kibria
はい、私はすでに行っていますが、それ以上のことはしません "string sqlInsFoodCode = @ "INSERT INTOコマンドがここに来ますが、私はこれをチェックしました" "、ローダーは無限の時間の読み込みを開始します – Kibria