Search Results

Search found 429 results on 18 pages for 'sqlexception'.

Page 18/18 | < Previous Page | 14 15 16 17 18 

  • Android: NullPointerException error in getting data in database

    - by Gil Viernes Marcelo
    This what happens in the system. 1. Admin login this is in other activity but i will not post it coz it has nothing to do with this (no problem) 2. Register user in system (using database no problem) 3. Click add user button (where existing user who register must display its name in ListView) Problem: When I click adduser to see if the system registered the user, it force close. CurrentUser.java package com.example.istronggyminstructor; import java.util.ArrayList; import android.os.Bundle; import android.app.Activity; import android.content.Context; import android.content.Intent; import android.database.Cursor; import android.view.Gravity; import android.view.LayoutInflater; import android.view.Menu; import android.view.View; import android.view.View.OnClickListener; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.WindowManager; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.ListView; import android.widget.PopupWindow; import android.widget.TextView; import android.widget.Toast; import java.util.ArrayList; import java.util.List; import java.util.Random; import com.example.istronggyminstructor.registeredUserList.Users; import android.content.ContentValues; import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; public class CurrentUsers extends Activity { private Button register; private Button adduser; EditText getusertext, getpass, getweight, textdisp; View popupview, popupview2; public static ArrayList<String> ArrayofName = new ArrayList<String>(); protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_current_users); register = (Button) findViewById(R.id.regbut); adduser = (Button) findViewById(R.id.addbut); register.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { LayoutInflater inflator = (LayoutInflater) getBaseContext() .getSystemService(LAYOUT_INFLATER_SERVICE); popupview = inflator.inflate(R.layout.popup, null); final PopupWindow popupWindow = new PopupWindow(popupview, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); popupWindow.showAtLocation(popupview, Gravity.CENTER, 0, 0); popupWindow.setFocusable(true); popupWindow.update(); Button dismissbtn = (Button) popupview.findViewById(R.id.close); dismissbtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { popupWindow.dismiss(); } }); popupWindow.showAsDropDown(register, 50, -30); } }); //Thread.setDefaultUncaughtExceptionHandler(new forceclose(this)); } public void registerUser(View v) { EditText username = (EditText) popupview.findViewById(R.id.usertext); EditText password = (EditText) popupview .findViewById(R.id.passwordtext); EditText weight = (EditText) popupview.findViewById(R.id.weight); String getUsername = username.getText().toString(); String getPassword = password.getText().toString(); String getWeight = weight.getText().toString(); dataHandler dbHandler = new dataHandler(this, null, null, 1); Users user = new Users(getUsername, getPassword, Integer.parseInt(getWeight)); dbHandler.addUsers(user); Toast.makeText(getApplicationContext(), "Registering...", Toast.LENGTH_SHORT).show(); } public void onClick_addUser(View v) { LayoutInflater inflator = (LayoutInflater) getBaseContext() .getSystemService(LAYOUT_INFLATER_SERVICE); popupview2 = inflator.inflate(R.layout.popup2, null); final PopupWindow popupWindow = new PopupWindow(popupview2, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); popupWindow.showAtLocation(popupview2, Gravity.CENTER, 0, -10); popupWindow.setFocusable(true); popupWindow.update(); Button dismissbtn = (Button) popupview2.findViewById(R.id.close2); dismissbtn.setOnClickListener(new OnClickListener() { @Override public void onClick(View arg0) { popupWindow.dismiss(); } }); popupWindow.showAsDropDown(register, 50, -30); dataHandler dbHandler = new dataHandler(this, null, null, 1); dbHandler.getAllUsers(); ListView list = (ListView)findViewById(R.layout.popup2); ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, ArrayofName); list.setAdapter(adapter); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.current_users, menu); return true; } } registeredUserList.java package com.example.istronggyminstructor; public class registeredUserList { public static class Users { private static int _id; private static String _users; private static String _password; private static int _weight; private static String[] _workoutlists; private static int _score; public Users() { } public Users(String username, String password, int weight) { _users = username; _password = password; _weight = weight; } public int getId() { return _id; } public static void setId(int id) { _id = id; } public String getUsers() { return _users; } public static void setUsers(String users) { _users = users; } public String getPassword(){ return _password; } public void setPassword(String password){ _password = password; } public int getWeight(){ return _weight; } public static void setWeight(int weight){ _weight = weight; } public String[] getWorkoutLists(){ return _workoutlists; } public void setWorkoutLists(String[] workoutlists){ _workoutlists = workoutlists; } public int score(){ return _score; } public void score(int score){ _score = score; } } } dataHandler.java package com.example.istronggyminstructor; import java.util.ArrayList; import java.util.List; import com.example.istronggyminstructor.registeredUserList.Users; import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; public class dataHandler extends SQLiteOpenHelper { private static final int DATABASE_VERSION = 1; private static final String DATABASE_NAME = "userInfo.db"; public static final String TABLE_USERINFO = "user"; public static final String COLUMN_ID = "_id"; public static final String COLUMN_USERNAME = "username"; public static final String COLUMN_PASSWORD = "password"; public static final String COLUMN_WEIGHT = "weight"; public dataHandler(Context context, String name, CursorFactory factory, int version) { super(context, DATABASE_NAME, factory, DATABASE_VERSION); } @Override public void onCreate(SQLiteDatabase db) { String CREATE_USER_TABLE = "CREATE TABLE " + TABLE_USERINFO + " (" + COLUMN_ID + " INTEGER PRIMARY KEY, " + COLUMN_USERNAME + " TEXT," + COLUMN_PASSWORD + " TEXT, " + COLUMN_WEIGHT + " INTEGER " + ");"; db.execSQL(CREATE_USER_TABLE); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { db.execSQL("DROP TABLE IF EXISTS " + TABLE_USERINFO); onCreate(db); } public void addUsers(Users user) { ContentValues values = new ContentValues(); values.put(COLUMN_USERNAME, user.getUsers()); values.put(COLUMN_PASSWORD, user.getPassword()); values.put(COLUMN_WEIGHT, user.getWeight()); SQLiteDatabase db = this.getWritableDatabase(); db.insert(TABLE_USERINFO, null, values); db.close(); } public Users findUsers(String username) { String query = "Select * FROM " + TABLE_USERINFO + " WHERE " + COLUMN_USERNAME + " = \"" + username + "\""; SQLiteDatabase db = this.getWritableDatabase(); Cursor cursor = db.rawQuery(query, null); Users user = new Users(); if (cursor.moveToFirst()) { cursor.moveToFirst(); Users.setUsers(cursor.getString(1)); //Users.setWeight(Integer.parseInt(cursor.getString(3))); not yet needed cursor.close(); } else { user = null; } db.close(); return user; } public List<Users> getAllUsers(){ List<Users> user = new ArrayList(); String selectQuery = "SELECT * FROM " + TABLE_USERINFO; SQLiteDatabase db = this.getWritableDatabase(); Cursor cursor = db.rawQuery(selectQuery, null); if (cursor.moveToFirst()) { do { Users users = new Users(); users.setUsers(cursor.getString(1)); String name = cursor.getString(1); CurrentUsers.ArrayofName.add(name); // Adding contact to list user.add(users); } while (cursor.moveToNext()); } // return user list return user; } public boolean deleteUsers(String username) { boolean result = false; String query = "Select * FROM " + TABLE_USERINFO + " WHERE " + COLUMN_USERNAME + " = \"" + username + "\""; SQLiteDatabase db = this.getWritableDatabase(); Cursor cursor = db.rawQuery(query, null); Users user = new Users(); if (cursor.moveToFirst()) { Users.setId(Integer.parseInt(cursor.getString(0))); db.delete(TABLE_USERINFO, COLUMN_ID + " = ?", new String[] { String.valueOf(user.getId()) }); cursor.close(); result = true; } db.close(); return result; } } Logcat 08-20 03:23:23.293: E/AndroidRuntime(16363): FATAL EXCEPTION: main 08-20 03:23:23.293: E/AndroidRuntime(16363): java.lang.IllegalStateException: Could not execute method of the activity 08-20 03:23:23.293: E/AndroidRuntime(16363): at android.view.View$1.onClick(View.java:3599) 08-20 03:23:23.293: E/AndroidRuntime(16363): at android.view.View.performClick(View.java:4204) 08-20 03:23:23.293: E/AndroidRuntime(16363): at android.view.View$PerformClick.run(View.java:17355) 08-20 03:23:23.293: E/AndroidRuntime(16363): at android.os.Handler.handleCallback(Handler.java:725) 08-20 03:23:23.293: E/AndroidRuntime(16363): at android.os.Handler.dispatchMessage(Handler.java:92) 08-20 03:23:23.293: E/AndroidRuntime(16363): at android.os.Looper.loop(Looper.java:137) 08-20 03:23:23.293: E/AndroidRuntime(16363): at android.app.ActivityThread.main(ActivityThread.java:5041) 08-20 03:23:23.293: E/AndroidRuntime(16363): at java.lang.reflect.Method.invokeNative(Native Method) 08-20 03:23:23.293: E/AndroidRuntime(16363): at java.lang.reflect.Method.invoke(Method.java:511) 08-20 03:23:23.293: E/AndroidRuntime(16363): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793) 08-20 03:23:23.293: E/AndroidRuntime(16363): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560) 08-20 03:23:23.293: E/AndroidRuntime(16363): at dalvik.system.NativeStart.main(Native Method) 08-20 03:23:23.293: E/AndroidRuntime(16363): Caused by: java.lang.reflect.InvocationTargetException 08-20 03:23:23.293: E/AndroidRuntime(16363): at java.lang.reflect.Method.invokeNative(Native Method) 08-20 03:23:23.293: E/AndroidRuntime(16363): at java.lang.reflect.Method.invoke(Method.java:511) 08-20 03:23:23.293: E/AndroidRuntime(16363): at android.view.View$1.onClick(View.java:3594) 08-20 03:23:23.293: E/AndroidRuntime(16363): ... 11 more 08-20 03:23:23.293: E/AndroidRuntime(16363): Caused by: java.lang.NullPointerException 08-20 03:23:23.293: E/AndroidRuntime(16363): at com.example.istronggyminstructor.CurrentUsers.onClick_addUser(CurrentUsers.java:118) 08-20 03:23:23.293: E/AndroidRuntime(16363): ... 14 more

    Read the article

  • "database already closed" is shown using a custom cursor adapter

    - by kiduxa
    I'm using a cursor with a custom adapter that extends SimpleCursorAdapter: public class ListWordAdapter extends SimpleCursorAdapter { private LayoutInflater inflater; private Cursor mCursor; private int mLayout; private String[] from; private int[] to; public ListWordAdapter(Context context, int layout, Cursor c, String[] from, int[] to, int flags) { super(context, layout, c, from, to, flags); this.mCursor = c; this.inflater = LayoutInflater.from(context); this.mLayout = layout; this.from = from; this.to = to; } private static class ViewHolder { //public ImageView img; public TextView name; public TextView type; public TextView translate; } @Override public View getView(int position, View convertView, ViewGroup parent) { if (mCursor.moveToPosition(position)) { ViewHolder holder; if (convertView == null) { convertView = inflater.inflate(mLayout, null); holder = new ViewHolder(); // holder.img = (ImageView) convertView.findViewById(R.id.img_row); holder.name = (TextView) convertView.findViewById(to[0]); holder.type = (TextView) convertView.findViewById(to[1]); holder.translate = (TextView) convertView.findViewById(to[2]); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.name.setText(mCursor.getString(mCursor.getColumnIndex(from[0]))); holder.type.setText(mCursor.getString(mCursor.getColumnIndex(from[1]))); holder.translate.setText(mCursor.getString(mCursor.getColumnIndex(from[2]))); // holder.img.setImageResource(img_resource); } return convertView; } } And in the main activity I call it as: adapter = new ListWordAdapter(getSherlockActivity(), R.layout.row_list_words, mCursorWords, from, to, 0); When a modification in the list is made, I call this method: public void onWordSaved() { WordDAO wordsDao = new WordSqliteDAO(); Cursor mCursorWords = wordsDao.list(getSherlockActivity()); adapter.changeCursor(mCursorWords); } The thing here is that this produces me this exception: 10-29 11:14:33.810: E/AndroidRuntime(18659): java.lang.IllegalStateException: database /data/data/com.example.palabrasdeldia/databases/palabrasDelDia (conn# 0) already closed Complete stack trace: 10-29 11:14:33.810: E/AndroidRuntime(18659): FATAL EXCEPTION: main 10-29 11:14:33.810: E/AndroidRuntime(18659): java.lang.IllegalStateException: database /data/data/com.example.palabrasdeldia/databases/palabrasDelDia (conn# 0) already closed 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.database.sqlite.SQLiteDatabase.verifyDbIsOpen(SQLiteDatabase.java:2123) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.database.sqlite.SQLiteDatabase.lock(SQLiteDatabase.java:398) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.database.sqlite.SQLiteDatabase.lock(SQLiteDatabase.java:390) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.database.sqlite.SQLiteQuery.fillWindow(SQLiteQuery.java:74) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.database.sqlite.SQLiteCursor.fillWindow(SQLiteCursor.java:311) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.database.sqlite.SQLiteCursor.onMove(SQLiteCursor.java:283) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.database.AbstractCursor.moveToPosition(AbstractCursor.java:173) 10-29 11:14:33.810: E/AndroidRuntime(18659): at com.example.palabrasdeldia.adapters.ListWordAdapter.getView(ListWordAdapter.java:42) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.AbsListView.obtainView(AbsListView.java:2128) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.ListView.makeAndAddView(ListView.java:1817) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.ListView.fillSpecific(ListView.java:1361) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.ListView.layoutChildren(ListView.java:1646) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.AbsListView.onLayout(AbsListView.java:1979) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.View.layout(View.java:9593) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.ViewGroup.layout(ViewGroup.java:3877) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1542) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.LinearLayout.layoutHorizontal(LinearLayout.java:1527) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.LinearLayout.onLayout(LinearLayout.java:1316) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.View.layout(View.java:9593) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.ViewGroup.layout(ViewGroup.java:3877) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.FrameLayout.onLayout(FrameLayout.java:400) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.View.layout(View.java:9593) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.ViewGroup.layout(ViewGroup.java:3877) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.support.v4.view.ViewPager.onLayout(ViewPager.java:1589) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.View.layout(View.java:9593) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.ViewGroup.layout(ViewGroup.java:3877) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.FrameLayout.onLayout(FrameLayout.java:400) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.View.layout(View.java:9593) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.ViewGroup.layout(ViewGroup.java:3877) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1542) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1403) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.LinearLayout.onLayout(LinearLayout.java:1314) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.View.layout(View.java:9593) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.ViewGroup.layout(ViewGroup.java:3877) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.FrameLayout.onLayout(FrameLayout.java:400) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.View.layout(View.java:9593) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.ViewGroup.layout(ViewGroup.java:3877) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1542) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1403) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.LinearLayout.onLayout(LinearLayout.java:1314) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.View.layout(View.java:9593) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.ViewGroup.layout(ViewGroup.java:3877) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.FrameLayout.onLayout(FrameLayout.java:400) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.View.layout(View.java:9593) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.ViewGroup.layout(ViewGroup.java:3877) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.widget.FrameLayout.onLayout(FrameLayout.java:400) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.View.layout(View.java:9593) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.ViewGroup.layout(ViewGroup.java:3877) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.ViewRoot.performTraversals(ViewRoot.java:1253) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.view.ViewRoot.handleMessage(ViewRoot.java:2017) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.os.Handler.dispatchMessage(Handler.java:99) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.os.Looper.loop(Looper.java:132) 10-29 11:14:33.810: E/AndroidRuntime(18659): at android.app.ActivityThread.main(ActivityThread.java:4028) 10-29 11:14:33.810: E/AndroidRuntime(18659): at java.lang.reflect.Method.invokeNative(Native Method) 10-29 11:14:33.810: E/AndroidRuntime(18659): at java.lang.reflect.Method.invoke(Method.java:491) 10-29 11:14:33.810: E/AndroidRuntime(18659): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:844) 10-29 11:14:33.810: E/AndroidRuntime(18659): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:602) 10-29 11:14:33.810: E/AndroidRuntime(18659): at dalvik.system.NativeStart.main(Native Method) If I use SimpleCursorAdapter directly instead of ListWordAdapter, it works fine. What's wrong with my custom adapter implementation? The line in bold in the stack trace corresponds with: if (mCursor.moveToPosition(position)) inside getView method. EDIT: I have created a custom class to manage DB operations as open and close: public class ConexionBD { private Context context; private SQLiteDatabase database; private DataBaseHelper dbHelper; public ConexionBD(Context context) { this.context = context; } public ConexionBD open() throws SQLException { this.dbHelper = DataBaseHelper.getInstance(context); this.database = dbHelper.getWritableDatabase(); database.execSQL("PRAGMA foreign_keys=ON"); return this; } public void close() { if (database.isOpen() && database != null) { dbHelper.close(); } } /*Getters y setters*/ public SQLiteDatabase getDatabase() { return database; } public void setDatabase(SQLiteDatabase database) { this.database = database; } } And this is my DataBaseHelper: public class DataBaseHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME = "myDb"; private static final int DATABASE_VERSION = 1; private static DataBaseHelper sInstance = null; public static DataBaseHelper getInstance(Context context) { // Use the application context, which will ensure that you // don't accidentally leak an Activity's context. // See this article for more information: http://bit.ly/6LRzfx if (sInstance == null) { sInstance = new DataBaseHelper(context.getApplicationContext()); } return sInstance; } @Override public void onCreate(SQLiteDatabase database) { ... } .... And this is an example of how I manage a query: public Cursor list(Context context) { ConexionBD conexion = new ConexionBD(context); Cursor mCursor = null; try{ conexion.open(); mCursor = conexion.getDatabase().query(DataBaseHelper.TABLE_WORD , null , null, null, null, null, Word.NAME); if (mCursor != null) { mCursor.moveToFirst(); } }finally{ conexion.close(); } return mCursor; } For every connection to the DB I open it and close it.

    Read the article

  • GridView does not display correcty sorted Data when i click column

    - by user329419
    Date column does not display in sorted in GridView using vb.net. In sql server the select query is returning records in sorted manner or in order by. But for some reason GridView does not display properly. it goes to an event preRenderComplete then it binds automatically Protected Sub Page_PreRenderComplete(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.PreRenderComplete 'Force the selections made in page_load to be shown in the gridview by causing a postback GridView1.DataBind() If GridView1.Rows.Count > 0 Then 'this is not counting correctly disable until i get it figured out '' lblMsg.Text = GridView1.Rows.Count.ToString + " Referrals" Else lblMsg.Text() = "No referrals to be processed" End If 'Turn off the Background Contolls 'If Not IsPostBack Then PanelBackendControls.Visible = False End Sub End Region _ Public Shared Function A02WF01_AdminView(ByVal strUserID As String, ByVal strTestMode As String, ByVal strSearchFieldValue As String, ByVal strDate As String) As DataTable Dim sel As String Dim conn As SqlConnection = New SqlConnection(WF01ConnectionString) If strSearchFieldValue <> "" And strTestMode = "ON" Then sel = "SELECT DISTINCT Since, WorkFlow_Step, " sel = sel & " Started_By, Client_FullName, Product_Desc, " sel = sel & " Branch_List, Event_AssignedID, DaysElapsed, Status,Instance_ID,Seq_ID,Form_Code " sel = sel & " FROM A02W01ViewAllTest " Dim WhereClause As String Dim OrderClause As String WhereClause = " WHERE ( Event_IsLatest = 1)" If strUserID <> "Admin" Then End If 'WhereClause = WhereClause + " AND WF_Start_UserID like " + "'" + strUserID + "')" WhereClause = WhereClause + " And( Started_By Like " + "'%" + strSearchFieldValue + "%'" WhereClause = WhereClause + " OR Client_FullName Like " + "'%" + strSearchFieldValue + "%'" 'WhereClause = WhereClause + " OR FullName Like " + "'%" + strSearchFieldValue + "%'" WhereClause = WhereClause + " OR Product_Desc Like " + "'%" + strSearchFieldValue + "%'" WhereClause = WhereClause + " OR Branch_List Like " + "'%" + strSearchFieldValue + "%'" WhereClause = WhereClause + " OR DaysElapsed Like " + "'%" + strSearchFieldValue + "%')" 'WhereClause = WhereClause + " OR Form_Code Like " + "'%" + strSearchFieldValue + "%')" OrderClause = " ORDER BY Since DESC" sel = sel + WhereClause + OrderClause ElseIf strSearchFieldValue <> "" And strTestMode <> "ON" Then sel = "SELECT DISTINCT Since, WorkFlow_Step, " sel = sel & " Started_By, Client_FullName, Product_Desc, " sel = sel & " Branch_List, Event_AssignedID, DaysElapsed, Status " sel = sel & " FROM A02W01ViewAll " Dim WhereClause As String Dim OrderClause As String WhereClause = " WHERE ( Event_IsLatest = 1)" If strUserID <> "Admin" Then End If 'WhereClause = WhereClause + " AND WF_Start_UserID like " + "'" + strUserID + "')" WhereClause = WhereClause + " AND( Started_By Like " + "'%" + strSearchFieldValue + "%'" WhereClause = WhereClause + " OR Client_FullName Like " + "'%" + strSearchFieldValue + "%'" 'WhereClause = WhereClause + " OR Client_LastName Like " + "'%" + strSearchFieldValue + "%'" WhereClause = WhereClause + " OR Product_Desc Like " + "'%" + strSearchFieldValue + "%'" WhereClause = WhereClause + " OR Branch_List Like " + "'%" + strSearchFieldValue + "%'" WhereClause = WhereClause + " OR DaysElapsed Like " + "'%" + strSearchFieldValue + "%'))" 'WhereClause = WhereClause + " OR Form_Code Like " + "'%" + strSearchFieldValue + "%'))" OrderClause = " ORDER BY Since DESC" sel = sel + WhereClause + OrderClause End If If strTestMode <> "ON" And strSearchFieldValue = "" Then sel = "SELECT DISTINCT Since, WorkFlow_Step, " sel = sel & " Started_By, Client_LastName, Client_FullName, Product_Desc, " sel = sel & " Branch_List, Event_AssignedID, DaysElapsed, Status " sel = sel & " FROM A02W01ViewAll " Dim WhereClause As String Dim OrderClause As String WhereClause = " WHERE Event_IsLatest = 1" 'WhereClause = WhereClause + " AND (Event_IsLatest = 1) " OrderClause = " ORDER BY Since DESC" sel = sel + WhereClause + OrderClause Else If strSearchFieldValue = "" And strTestMode = "ON" And strDate = "" Then sel = "SELECT DISTINCT Since, WorkFlow_Step, " sel = sel & " Started_By, Client_FullName, Product_Desc, " sel = sel & " Branch_List, Event_AssignedID, DaysElapsed, Status, Instance_ID,Seq_ID,Form_Code " sel = sel & " FROM A02W01ViewAllTest " Dim WhereClause As String Dim OrderClause As String WhereClause = " WHERE Event_IsLatest = 1" 'Display everything for Admin ' Comment below code 'If strUserID <> "Admin" Then WhereClause = WhereClause + " AND WF_Start_UserID like " + "'" + strUserID + "'" OrderClause = " ORDER BY Since DESC" sel = sel + WhereClause + OrderClause ElseIf strSearchFieldValue = "" And strTestMode = "ON" And strDate <> "" Then sel = "" sel = sel & "SELECT TOP 100 PERCENT Since, WorkFlow_Step, " sel = sel & "Started_By, Client_Fullname, Product_Desc, " sel = sel & "Branch_List, Event_AssignedID, DaysElapsed, Status, " sel = sel & "Instance_ID, Seq_ID, Form_Code " sel = sel & " FROM A02W01ViewDistinct " Dim WhereClause As String Dim OrderClause As String WhereClause = " WHERE Event_IsLatest = 1" 'Display everything for Admin ' Comment below code 'If strUserID <> "Admin" Then WhereClause = WhereClause + " AND WF_Start_UserID like " + "'" + strUserID + "'" OrderClause = " ORDER BY YEAR(Since) DESC, MONTH(Since) DESC, DAY(Since) DESC" sel = sel + WhereClause + OrderClause End If End If Dim da As SqlDataAdapter = New SqlDataAdapter(sel, conn) Dim ds As DataSet = New DataSet() Try conn.Open() da.Fill(ds, "odsA02_Tracking") conn.Close() Catch e As SqlException WFClassLib.PageError() Finally conn.Close() End Try If ds.Tables("odsA02_Tracking") IsNot Nothing Then _ Return ds.Tables("odsA02_Tracking") 'Return ds 'If ds.Tables("odsA02_Tracking") Is Nothing Then Return Nothing 'End If End Function BorderStyle="Outset" CellPadding="4" DataSourceID="odsA02_Tracking" ForeColor="#333333" GridLines="Vertical" Style="border-right: #0000ff thin solid; table-layout: auto; border-top: #0000ff thin solid; font-size: x-small; border-left: #0000ff thin solid; border-bottom: #0000ff thin solid; font-family: Arial; border-collapse: separate" Font-Size="Small" PageSize="30" <Columns> <asp:CommandField ShowSelectButton="True" /> <asp:boundfield datafield="Since" HeaderText="Submit Date" ReadOnly=True SortExpression="Since" /> <asp:BoundField DataField="Started_By" HeaderText="Submitted By" SortExpression="Started_By" /> <asp:BoundField DataField="Client_FullName" HeaderText="Client Name" ReadOnly="True" SortExpression="Client_FullName" /> <asp:BoundField DataField="Product_Desc" HeaderText="Product" ReadOnly="True" SortExpression="Product_Desc" /> <asp:BoundField DataField="Branch_List" HeaderText="Branch" ReadOnly="True" SortExpression="Branch_List" /> <asp:BoundField DataField="Event_AssignedID" HeaderText="Assigned To" ReadOnly="True" SortExpression="Event_AssignedID" /> <asp:BoundField DataField="DaysElapsed" HeaderText="Days Open" ReadOnly="True" SortExpression="DaysElapsed" /> <asp:BoundField DataField="Status" HeaderText="Status" SortExpression="Status" /> <asp:TemplateField> <ItemTemplate> <asp:HiddenField ID=hdnInstanceID Value='<%#Eval("Instance_ID") %>' runat=server> </asp:HiddenField> </ItemTemplate> </asp:TemplateField> <asp:TemplateField> <ItemTemplate> <asp:HiddenField ID=hdnSeqID Value='<%#Eval("Seq_ID") %>' runat=server/> </ItemTemplate> </asp:TemplateField> <asp:TemplateField> <ItemTemplate> <asp:HiddenField ID=hdnFormCode Value='<%#Eval("Form_Code") %>' runat=server/> </ItemTemplate> </asp:TemplateField> </Columns> </asp:GridView> &nbsp;&nbsp; <asp:Label ID="lblMsg" runat="server" Style="font-size: small; color: red; font-family: Arial" Width="525px" Font-Bold="True"></asp:Label><br /> <br /> <asp:Button ID="btnReturn" runat="server" Text="Return" /><br /> <br /> <asp:Label ID="lbltxtUserID" runat="server" Text="txtUserID" Visible="False"></asp:Label> <asp:TextBox ID="txtUserID" runat="server" Visible="False" Width="226px"></asp:TextBox><br /> <asp:Label ID="label4" runat="server" Text="TestModeOn" Visible="false"></asp:Label> <asp:TextBox ID="TestModeOn" runat="server" Visible="False" Width="226px"></asp:TextBox><br /> <br /> <asp:Label ID="lblSearchUserEntered" runat="server" Visible="false" Text="searchText" ></asp:Label> <asp:TextBox ID="searchText" runat="server" Visible="False" Width ="226px" ></asp:TextBox> <br /> <asp:Label ID="Label1" runat="server" Text="txtInstance_ID" Visible="False"></asp:Label> <asp:TextBox ID="txtInstance_ID" runat="server" Visible="False" Width="226px"></asp:TextBox><br /> <asp:Label ID="Label2" runat="server" Text="txtSeq_ID" Visible="False"></asp:Label> <asp:TextBox ID="txtSeq_ID" runat="server" Visible="False" Width="226px"></asp:TextBox><br /> <asp:Label ID="Label3" runat="server" Text="txtForm_Code" Visible="False"></asp:Label> <asp:TextBox ID="txtForm_Code" runat="server" Visible="False" Width="226px"></asp:TextBox><br /> <br /> <asp:Label ID="lblSince" runat="server" Visible="false" Text="Since" ></asp:Label> <asp:TextBox ID="SortSince" runat="server" Visible="False" Width ="226px" ></asp:TextBox> <br /> <br /> <asp:ObjectDataSource ID="odsA02_Tracking" runat="server" OldValuesParameterFormatString="original_{0}" SelectMethod="A02WF01_AdminView" TypeName="WFA02DataObjects"> <SelectParameters> <asp:ControlParameter ControlID="txtUserID" Name="strUserID" PropertyName="Text" Type="String" /> <asp:ControlParameter ControlID="TestModeOn" Name="strTestMode" PropertyName="Text" Type="String" /> <asp:ControlParameter ControlID="searchText" Name="strSearchFieldValue" PropertyName="Text" Type="String" /> <asp:ControlParameter ControlID="SortSince" Name="strDate" PropertyName="Text" Type="String" /> </SelectParameters> </asp:ObjectDataSource> </div> </form>

    Read the article

  • Bulk inserting best way to about it? + Helping me understand fully what I found so far

    - by chobo2
    Hi So I saw this post here and read it and it seems like bulk copy might be the way to go. http://stackoverflow.com/questions/682015/whats-the-best-way-to-bulk-database-inserts-from-c I still have some questions and want to know how things actually work. So I found 2 tutorials. http://www.codeproject.com/KB/cs/MultipleInsertsIn1dbTrip.aspx#_Toc196622241 http://www.codeproject.com/KB/linq/BulkOperations_LinqToSQL.aspx First way uses 2 ado.net 2.0 features. BulkInsert and BulkCopy. the second one uses linq to sql and OpenXML. This sort of appeals to me as I am using linq to sql already and prefer it over ado.net. However as one person pointed out in the posts what he just going around the issue at the cost of performance( nothing wrong with that in my opinion) First I will talk about the 2 ways in the first tutorial I am using VS2010 Express, .net 4.0, MVC 2.0, SQl Server 2005 Is ado.net 2.0 the most current version? Based on the technology I am using, is there some updates to what I am going to show that would improve it somehow? Is there any thing that these tutorial left out that I should know about? BulkInsert I am using this table for all the examples. CREATE TABLE [dbo].[TBL_TEST_TEST] ( ID INT IDENTITY(1,1) PRIMARY KEY, [NAME] [varchar](50) ) SP Code USE [Test] GO /****** Object: StoredProcedure [dbo].[sp_BatchInsert] Script Date: 05/19/2010 15:12:47 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[sp_BatchInsert] (@Name VARCHAR(50) ) AS BEGIN INSERT INTO TBL_TEST_TEST VALUES (@Name); END C# Code /// <summary> /// Another ado.net 2.0 way that uses a stored procedure to do a bulk insert. /// Seems slower then "BatchBulkCopy" way and it crashes when you try to insert 500,000 records in one go. /// http://www.codeproject.com/KB/cs/MultipleInsertsIn1dbTrip.aspx#_Toc196622241 /// </summary> private static void BatchInsert() { // Get the DataTable with Rows State as RowState.Added DataTable dtInsertRows = GetDataTable(); SqlConnection connection = new SqlConnection(connectionString); SqlCommand command = new SqlCommand("sp_BatchInsert", connection); command.CommandType = CommandType.StoredProcedure; command.UpdatedRowSource = UpdateRowSource.None; // Set the Parameter with appropriate Source Column Name command.Parameters.Add("@Name", SqlDbType.VarChar, 50, dtInsertRows.Columns[0].ColumnName); SqlDataAdapter adpt = new SqlDataAdapter(); adpt.InsertCommand = command; // Specify the number of records to be Inserted/Updated in one go. Default is 1. adpt.UpdateBatchSize = 1000; connection.Open(); int recordsInserted = adpt.Update(dtInsertRows); connection.Close(); } So first thing is the batch size. Why would you set a batch size to anything but the number of records you are sending? Like I am sending 500,000 records so I did a Batch size of 500,000. Next why does it crash when I do this? If I set it to 1000 for batch size it works just fine. System.Data.SqlClient.SqlException was unhandled Message="A transport-level error has occurred when sending the request to the server. (provider: Shared Memory Provider, error: 0 - No process is on the other end of the pipe.)" Source=".Net SqlClient Data Provider" ErrorCode=-2146232060 Class=20 LineNumber=0 Number=233 Server="" State=0 StackTrace: at System.Data.Common.DbDataAdapter.UpdatedRowStatusErrors(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount) at System.Data.Common.DbDataAdapter.UpdatedRowStatus(RowUpdatedEventArgs rowUpdatedEvent, BatchCommandInfo[] batchCommands, Int32 commandCount) at System.Data.Common.DbDataAdapter.Update(DataRow[] dataRows, DataTableMapping tableMapping) at System.Data.Common.DbDataAdapter.UpdateFromDataTable(DataTable dataTable, DataTableMapping tableMapping) at System.Data.Common.DbDataAdapter.Update(DataTable dataTable) at TestIQueryable.Program.BatchInsert() in C:\Users\a\Downloads\TestIQueryable\TestIQueryable\TestIQueryable\Program.cs:line 124 at TestIQueryable.Program.Main(String[] args) in C:\Users\a\Downloads\TestIQueryable\TestIQueryable\TestIQueryable\Program.cs:line 16 InnerException: Time it took to insert 500,000 records with insert batch size of 1000 took "2 mins and 54 seconds" Of course this is no official time I sat there with a stop watch( I am sure there are better ways but was too lazy to look what they where) So I find that kinda slow compared to all my other ones(expect the linq to sql insert one) and I am not really sure why. Next I looked at bulkcopy /// <summary> /// An ado.net 2.0 way to mass insert records. This seems to be the fastest. /// http://www.codeproject.com/KB/cs/MultipleInsertsIn1dbTrip.aspx#_Toc196622241 /// </summary> private static void BatchBulkCopy() { // Get the DataTable DataTable dtInsertRows = GetDataTable(); using (SqlBulkCopy sbc = new SqlBulkCopy(connectionString, SqlBulkCopyOptions.KeepIdentity)) { sbc.DestinationTableName = "TBL_TEST_TEST"; // Number of records to be processed in one go sbc.BatchSize = 500000; // Map the Source Column from DataTabel to the Destination Columns in SQL Server 2005 Person Table // sbc.ColumnMappings.Add("ID", "ID"); sbc.ColumnMappings.Add("NAME", "NAME"); // Number of records after which client has to be notified about its status sbc.NotifyAfter = dtInsertRows.Rows.Count; // Event that gets fired when NotifyAfter number of records are processed. sbc.SqlRowsCopied += new SqlRowsCopiedEventHandler(sbc_SqlRowsCopied); // Finally write to server sbc.WriteToServer(dtInsertRows); sbc.Close(); } } This one seemed to go really fast and did not even need a SP( can you use SP with bulk copy? If you can would it be better?) BatchCopy had no problem with a 500,000 batch size.So again why make it smaller then the number of records you want to send? I found that with BatchCopy and 500,000 batch size it took only 5 seconds to complete. I then tried with a batch size of 1,000 and it only took 8 seconds. So much faster then the bulkinsert one above. Now I tried the other tutorial. USE [Test] GO /****** Object: StoredProcedure [dbo].[spTEST_InsertXMLTEST_TEST] Script Date: 05/19/2010 15:39:03 ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[spTEST_InsertXMLTEST_TEST](@UpdatedProdData nText) AS DECLARE @hDoc int exec sp_xml_preparedocument @hDoc OUTPUT,@UpdatedProdData INSERT INTO TBL_TEST_TEST(NAME) SELECT XMLProdTable.NAME FROM OPENXML(@hDoc, 'ArrayOfTBL_TEST_TEST/TBL_TEST_TEST', 2) WITH ( ID Int, NAME varchar(100) ) XMLProdTable EXEC sp_xml_removedocument @hDoc C# code. /// <summary> /// This is using linq to sql to make the table objects. /// It is then serailzed to to an xml document and sent to a stored proedure /// that then does a bulk insert(I think with OpenXML) /// http://www.codeproject.com/KB/linq/BulkOperations_LinqToSQL.aspx /// </summary> private static void LinqInsertXMLBatch() { using (TestDataContext db = new TestDataContext()) { TBL_TEST_TEST[] testRecords = new TBL_TEST_TEST[500000]; for (int count = 0; count < 500000; count++) { TBL_TEST_TEST testRecord = new TBL_TEST_TEST(); testRecord.NAME = "Name : " + count; testRecords[count] = testRecord; } StringBuilder sBuilder = new StringBuilder(); System.IO.StringWriter sWriter = new System.IO.StringWriter(sBuilder); XmlSerializer serializer = new XmlSerializer(typeof(TBL_TEST_TEST[])); serializer.Serialize(sWriter, testRecords); db.insertTestData(sBuilder.ToString()); } } So I like this because I get to use objects even though it is kinda redundant. I don't get how the SP works. Like I don't get the whole thing. I don't know if OPENXML has some batch insert under the hood but I do not even know how to take this example SP and change it to fit my tables since like I said I don't know what is going on. I also don't know what would happen if the object you have more tables in it. Like say I have a ProductName table what has a relationship to a Product table or something like that. In linq to sql you could get the product name object and make changes to the Product table in that same object. So I am not sure how to take that into account. I am not sure if I would have to do separate inserts or what. The time was pretty good for 500,000 records it took 52 seconds The last way of course was just using linq to do it all and it was pretty bad. /// <summary> /// This is using linq to sql to to insert lots of records. /// This way is slow as it uses no mass insert. /// Only tried to insert 50,000 records as I did not want to sit around till it did 500,000 records. /// http://www.codeproject.com/KB/linq/BulkOperations_LinqToSQL.aspx /// </summary> private static void LinqInsertAll() { using (TestDataContext db = new TestDataContext()) { db.CommandTimeout = 600; for (int count = 0; count < 50000; count++) { TBL_TEST_TEST testRecord = new TBL_TEST_TEST(); testRecord.NAME = "Name : " + count; db.TBL_TEST_TESTs.InsertOnSubmit(testRecord); } db.SubmitChanges(); } } I did only 50,000 records and that took over a minute to do. So I really narrowed it done to the linq to sql bulk insert way or bulk copy. I am just not sure how to do it when you have relationship for either way. I am not sure how they both stand up when doing updates instead of inserts as I have not gotten around to try it yet. I don't think I will ever need to insert/update more than 50,000 records at one type but at the same time I know I will have to do validation on records before inserting so that will slow it down and that sort of makes linq to sql nicer as your got objects especially if your first parsing data from a xml file before you insert into the database. Full C# code using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml.Serialization; using System.Data; using System.Data.SqlClient; namespace TestIQueryable { class Program { private static string connectionString = ""; static void Main(string[] args) { BatchInsert(); Console.WriteLine("done"); } /// <summary> /// This is using linq to sql to to insert lots of records. /// This way is slow as it uses no mass insert. /// Only tried to insert 50,000 records as I did not want to sit around till it did 500,000 records. /// http://www.codeproject.com/KB/linq/BulkOperations_LinqToSQL.aspx /// </summary> private static void LinqInsertAll() { using (TestDataContext db = new TestDataContext()) { db.CommandTimeout = 600; for (int count = 0; count < 50000; count++) { TBL_TEST_TEST testRecord = new TBL_TEST_TEST(); testRecord.NAME = "Name : " + count; db.TBL_TEST_TESTs.InsertOnSubmit(testRecord); } db.SubmitChanges(); } } /// <summary> /// This is using linq to sql to make the table objects. /// It is then serailzed to to an xml document and sent to a stored proedure /// that then does a bulk insert(I think with OpenXML) /// http://www.codeproject.com/KB/linq/BulkOperations_LinqToSQL.aspx /// </summary> private static void LinqInsertXMLBatch() { using (TestDataContext db = new TestDataContext()) { TBL_TEST_TEST[] testRecords = new TBL_TEST_TEST[500000]; for (int count = 0; count < 500000; count++) { TBL_TEST_TEST testRecord = new TBL_TEST_TEST(); testRecord.NAME = "Name : " + count; testRecords[count] = testRecord; } StringBuilder sBuilder = new StringBuilder(); System.IO.StringWriter sWriter = new System.IO.StringWriter(sBuilder); XmlSerializer serializer = new XmlSerializer(typeof(TBL_TEST_TEST[])); serializer.Serialize(sWriter, testRecords); db.insertTestData(sBuilder.ToString()); } } /// <summary> /// An ado.net 2.0 way to mass insert records. This seems to be the fastest. /// http://www.codeproject.com/KB/cs/MultipleInsertsIn1dbTrip.aspx#_Toc196622241 /// </summary> private static void BatchBulkCopy() { // Get the DataTable DataTable dtInsertRows = GetDataTable(); using (SqlBulkCopy sbc = new SqlBulkCopy(connectionString, SqlBulkCopyOptions.KeepIdentity)) { sbc.DestinationTableName = "TBL_TEST_TEST"; // Number of records to be processed in one go sbc.BatchSize = 500000; // Map the Source Column from DataTabel to the Destination Columns in SQL Server 2005 Person Table // sbc.ColumnMappings.Add("ID", "ID"); sbc.ColumnMappings.Add("NAME", "NAME"); // Number of records after which client has to be notified about its status sbc.NotifyAfter = dtInsertRows.Rows.Count; // Event that gets fired when NotifyAfter number of records are processed. sbc.SqlRowsCopied += new SqlRowsCopiedEventHandler(sbc_SqlRowsCopied); // Finally write to server sbc.WriteToServer(dtInsertRows); sbc.Close(); } } /// <summary> /// Another ado.net 2.0 way that uses a stored procedure to do a bulk insert. /// Seems slower then "BatchBulkCopy" way and it crashes when you try to insert 500,000 records in one go. /// http://www.codeproject.com/KB/cs/MultipleInsertsIn1dbTrip.aspx#_Toc196622241 /// </summary> private static void BatchInsert() { // Get the DataTable with Rows State as RowState.Added DataTable dtInsertRows = GetDataTable(); SqlConnection connection = new SqlConnection(connectionString); SqlCommand command = new SqlCommand("sp_BatchInsert", connection); command.CommandType = CommandType.StoredProcedure; command.UpdatedRowSource = UpdateRowSource.None; // Set the Parameter with appropriate Source Column Name command.Parameters.Add("@Name", SqlDbType.VarChar, 50, dtInsertRows.Columns[0].ColumnName); SqlDataAdapter adpt = new SqlDataAdapter(); adpt.InsertCommand = command; // Specify the number of records to be Inserted/Updated in one go. Default is 1. adpt.UpdateBatchSize = 500000; connection.Open(); int recordsInserted = adpt.Update(dtInsertRows); connection.Close(); } private static DataTable GetDataTable() { // You First need a DataTable and have all the insert values in it DataTable dtInsertRows = new DataTable(); dtInsertRows.Columns.Add("NAME"); for (int i = 0; i < 500000; i++) { DataRow drInsertRow = dtInsertRows.NewRow(); string name = "Name : " + i; drInsertRow["NAME"] = name; dtInsertRows.Rows.Add(drInsertRow); } return dtInsertRows; } static void sbc_SqlRowsCopied(object sender, SqlRowsCopiedEventArgs e) { Console.WriteLine("Number of records affected : " + e.RowsCopied.ToString()); } } }

    Read the article

< Previous Page | 14 15 16 17 18