코드는 SQL 삽입 공격에 개방되어 있으며 SQL 문 작성 및 후속 단계 호출이 실패하는 이유를 설명 할 수 있습니다.
대신 Bind 매개 변수 및 해당 Bind 호출을 사용하여 Prepared statement을 최대한 활용하십시오. 다음과 같이 코드를 적응 :
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을주고 싶어, 여기에 지원하는 클래스입니다 :
// 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);
}
}
당신이'connStatement.Step()를 변경하는 경우,'var에 밥 = connStatement.Step()'로,'무엇을 100, 199, 200, 201 행의'bob' 값입니까? – mjwills
"문자열 sqlInsFoodCode = .........."이후 Visual Studio로 돌아 오지 않는 이유는 알 수 없습니다. ( – Kibria
예, 이미 완료되었지만 넘어 설 수는 없습니다. "문자열 sqlInsFoodCode = @ "INSERT INTO 명령이 여기에 오는데 아무 것도 잘못하지 않았습니다." "로더가 무한 시간로드되기 시작합니다. – Kibria