我从WCF获取了大量行,然后我想在我的本地SQLite DB中逐个插入这些行。为此,我正在使用SQLItePCL。使用调试器,我检测到大约有900行,然后我开始一个for循环并逐个插入所有这些行。但它没有插入一行,并且加载器(我使用加载器来显示何时插入数据)加载无限时间。我正在检查LocalState文件夹中我的本地数据库的大小,但它没有增加,这意味着什么也没发生,但我的应用程序也没有崩溃。当行号小于200时,一切都很好。下面是插入数据的代码:
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)时,它无法在每个内部循环并评估其值,它会卡住构建sql字符串,但是当我给出静态值时它工作正常。有什么帮助吗?
答案 0 :(得分:0)
您的代码对SQL注入攻击是开放的,这也可能解释了为什么构建SQL语句和后续步骤调用失败。
通过引入Bind参数和相应的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();
}
}
}
在10秒钟内插入100行,这个时间是线性的。
在测试期间,您可能希望使用":memory:"
作为数据库名称。这将为您提供一个内存存储,比在磁盘上写入快得多。
如果有人想给这个测试人员,这里有支持类:
// 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);
}
}