Лучший вариант - начать транзакцию перед циклом, выполнить каждый оператор, а не добавлять его в stringbuilder, и фиксировать после цикла (или каждого n числа записей).
Кроме того, вы должны использовать параметризованную команду, что-то вроде:
SqlCeCommand oCommand = conn.CreateCommand();
oCommand.CommandText = "insert into contacts(name, emails) values(?, ?)";
// I can't remember if the param names need @ or not
oCommand.Parameters.Add("@name", SqlDbType.VarChar);
oCommand.Parameters.Add("@email", SqlDbType.VarChar);
SqlCeTransaction oTrans = conn.BeginTransaction();
try {
foreach (KeyValuePair<string, string> key in list) {
oCommand.Parameters[0].Value = key.Key;
oCommand.Parameters[1].Value = key.Value;
oCommand.ExecuteNonQuery();
}
oTrans.Commit();
} catch (Exception ex) {
oTrans.Rollback();
}
В качестве альтернативы, вы можете использовать SQL Compact Bulk Insert Library из codeplex. Я полагаю, что для этого используется TableDirect SqlCeCommand поверх SqlCeResultSet, который должен обходить процессор запросов и работать с максимальной скоростью.