Android; SQLite database Cursor is null. It should not be. I don't know why it is - android-cursor

I had a method which fetched records from an sqlite database but after a while i changed it a little and made a secondary method for fetching specific records with user entered information.
I don't know why but my original method is returning null now.
CardDbAdapter:
public CarddbAdapter open2() throws SQLException {
String myPath = DB_PATH + DB_NAME;
myDatabaseR = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READONLY);
myDatabaseW = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READWRITE);
return this;
}
public void MyDatabaseClose() {
myDatabaseW.close();
myDatabaseR.close();
}
public ArrayList<String> getAllCardNames() {
ArrayList<String> returnedAllCardNames;
ArrayList<String> NoResults;
ArrayList<String> NoResults2;
NoResults = new ArrayList<String>();
NoResults.add("cursor is null");
NoResults2 = new ArrayList<String>();
NoResults2.add("No similar cards found.");
returnedAllCardNames = new ArrayList<String>();
/*String sqlquery_cardNames = "SELECT " + KEY_CARDNAME
+ " FROM cards WHERE card_name like '%" + passedName
+ "%' ORDER BY card_name ASC";*/
//String sqlquery_cardNames;
String sqlquery_cardNames = "SELECT DISTINCT card_name FROM cards";
Cursor c_cardNames;
c_cardNames = myDatabaseW.rawQuery(sqlquery_cardNames, null);
c_cardNames.moveToFirst();
if (c_cardNames != null) {
do {
if (c_cardNames.getCount() > 0) {
String returnedName = c_cardNames.getString(c_cardNames
.getColumnIndex(KEY_CARDNAME));
returnedAllCardNames.add(returnedName);
} else {
return NoResults2;
}
} while (c_cardNames.moveToNext());
}
return NoResults;
}
How i am using it:
CarddbAdapter yugiohDB = new CarddbAdapter(this);
yugiohDB.open2();
search_results = (ListView) findViewById(R.id.lvSearchResults);
search_results.setOnItemClickListener(this);
ArrayList<String> returnedCards_list1 = new ArrayList<String>();
returnedCards_list1.addAll(yugiohDB.getAllCardNames());
listAdapter = new ArrayAdapter<String>(SearchMode_Simple.this,
android.R.layout.simple_list_item_1, returnedCards_list1);
search_results.setAdapter(listAdapter);
yugiohDB.MyDatabaseClose();
Any help would be appreciated.
If you would like to see what this is actually supposed to do then download my app called Yugioh Library + Tools. Click the Search Library button from the main menu and then the button Simple Search. It should be displaying a list of cards from the database.
The reason i was changing it is because i'm setting up Spinners so users can choose different trading card sets to choose some which would then list all the cards from that specific set.

Fixed. I forgot to return the string array "returnedAllCardNames" which was holding the names of all process card records after the do while loop.

Related

am working on updating a single attribute in the User Model which is the balance attribute,

how I can update a single value for an already existing row in the db by only having a parameters that I want to add it to this attribute
here is my code for a trivial way but didnt work
public bool BuyBook(int BookId, int UserId, int BookPrice){
using (var ctx = new OnlineBooksEntities())
{
User updatedCustomer = (from c in ctx.Users
where c.UserId == UserId
select c).FirstOrDefault();
updatedCustomer.Balance = BookPrice;
ctx.SaveChanges();
}
this.DeleteBook(BookId);
return true;
}
Add an sql query to the method solves the update aim
public bool BuyBook(int BookId, int UserId, int BookPrice)
{
try
{
using (var ctx = new OnlineBooksEntities())
{
User user = ctx.Users.Where(x => x.UserId == UserId).FirstOrDefault();
BookPrice = (int)user.Balance + BookPrice;
int noOfRowUpdated =
ctx.Database.ExecuteSqlCommand("Update Users set Balance = "+BookPrice+ " where UserId ="+UserId);
}
Updating basically means changing an existing row's value. Since you mentioned EF, you can do this by retrieving the object, changing its value, and saving it back. Thus you can do something like this:
using (var db = new MyContextDB())
{
var result = db.Books.SingleOrDefault(b => b.BookPrice == bookPrice);
if (result != null)
{
result.SomeValue = "Your new value here";
db.SaveChanges();
}
}

Xamarin Android, get contact mobile number by using CursorLoader with selection and selection args

I'm trying to get contact details of a contact that the user picks from the contacts list in Android using Intent as the following code:
Intent Intent = new Intent(Intent.ActionPick, ContactsContract.Contacts.ContentUri);
Intent.SetType(ContactsContract.Contacts.ContentType);
StartActivityForResult(Intent, 3);
Now on the Intent results I run the following code to get specific contact information:
public override void OnActivityResult(int requestCode, int resultCode, Intent data)
{
if (requestCode == 3 && resultCode == -1 && data != null) //result code -1 means OK 0 Means cancelled Result.Ok
{
var ContactData = data.Data;
string ID = "";
string name = "";
string address = "";
byte[] picture = new byte[0];
List<string> numbers = new List<string>();
List<string> emails = new List<string>();
string mobile = "";
string email = "";
string selectionString = "id = ?";
string[] columnsNames = new string[] {
ContactsContract.Contacts.InterfaceConsts.Id,
ContactsContract.Contacts.InterfaceConsts.DisplayName,
ContactsContract.Contacts.InterfaceConsts.PhotoUri
};
var loader = new CursorLoader(Statics.mainActivity, ContactData, null, null, null, null);
var cursor = (ICursor)loader.LoadInBackground();
if (cursor.MoveToFirst())
{
ID = cursor.GetString(cursor.GetColumnIndex(columnsNames[0]));
name = cursor.GetString(cursor.GetColumnIndex(columnsNames[1]));
picture = cursor.GetBlob(cursor.GetColumnIndex(columnsNames[2]));
}
//Store Contact ID
string[] selectionStringArgs = new string[] { ID };
//Phone Numbers
string[] columnsNames2 = new string[] {
ContactsContract.CommonDataKinds.Phone.Number
};
var loader2 = new CursorLoader(Statics.mainActivity, ContactsContract.CommonDataKinds.Phone.ContentUri, columnsNames2, selectionString, selectionStringArgs, null);
var cursor2 = (ICursor)loader2.LoadInBackground();
while (cursor2.MoveToNext())
{
numbers.Add(cursor2.GetString(cursor2.GetColumnIndex(columnsNames2[0])));
}
//Email Address
string[] columnsNames3 = new string[] {
ContactsContract.CommonDataKinds.Email.Address
};
var loader3 = new CursorLoader(Statics.mainActivity, ContactsContract.CommonDataKinds.Email.ContentUri, columnsNames3, selectionString, selectionStringArgs, null);
var cursor3 = (ICursor)loader3.LoadInBackground();
while (cursor3.MoveToNext())
{
emails.Add(cursor3.GetString(cursor3.GetColumnIndex(columnsNames3[0])));
}
int TempRecepitntID = 0;
EmployeesViewModel tempRecipent = new EmployeesViewModel();
TempRecepitntID = Statics.mainActivity.currentViewModel.SelectedChat.ReceiverEmployee;
foreach (EmployeesViewModel evm in Statics.mainActivity.currentViewModel.Employees)
{
if (evm.ID == TempRecepitntID)
tempRecipent = evm;
}
new Android.Support.V7.App.AlertDialog.Builder(Statics.mainActivity)
.SetPositiveButton("Yes", (sender1, args) =>
{
Statics.mainActivity.currentViewModel.AddMessage(picture, tempRecipent, Statics.mainActivity.currentViewModel.SelectedChat.ID, "contact", 0, "", name, numbers[0], mobile, email, address);
})
.SetNegativeButton("No", (sender1, args) =>
{
// cancel
})
.SetMessage("Are you shure you want to send?")
.SetTitle("System Message")
.Show();
}
}
The problem is I want to retrieve only the information of the contact that the user selected but what I get is all other contacts data is retrieved so I tried to use the selection and selectionargs parameters of CursorLoader by setting string selectionString = "id = ?"; and selectionArgs to string[] selectionStringArgs = new string[] { ID }; the ID value is retrieved from the following code :
if (cursor.MoveToFirst())
{
ID = cursor.GetString(cursor.GetColumnIndex(columnsNames[0]));
name = cursor.GetString(cursor.GetColumnIndex(columnsNames[1]));
picture = cursor.GetBlob(cursor.GetColumnIndex(columnsNames[2]));
}
//Store Contact ID
string[] selectionStringArgs = new string[] { ID };
//Phone Numbers
string[] columnsNames2 = new string[] {
ContactsContract.CommonDataKinds.Phone.Number
};
But now it returns 0 results, I couldn't find anything on the internet that applies to Xamarin android, Please help.
Thanks,
Finally I found the solution, I used the following string in the selection parameter of the cursorloader method:
string selectionString = ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId + "=" + ID;
and now only the selected contact numbers are retrieved.
I hope this will help someone else.
In additional information of #TMSL, I add the code afer this bloque
if (cursor.MoveToFirst())
{
ID = cursor.GetString(cursor.GetColumnIndex(columnsNames[0]));
name = cursor.GetString(cursor.GetColumnIndex(columnsNames[1]));
picture = cursor.GetBlob(cursor.GetColumnIndex(columnsNames[2]));
}
Here
selectionString = ContactsContract.CommonDataKinds.Phone.InterfaceConsts.ContactId + "=" + ID;
Then I changed the parameters used in the definition of variable Loader2, converting selectionStringArgs in null.
var loader2 = new CursorLoader(this.Activity, ContactsContract.CommonDataKinds.Phone.ContentUri, columnsNames2, selectionString, null,null);
var cursor2 = (ICursor)loader2.LoadInBackground();
I found this documentation from xamarin guides
Uri – The fully qualified name of the ContentProvider.
Projection – Specification of which columns to select for the cursor.
Selection – Similar to a SQL WHERE clause.
SelectionArgs – Parameters to be substituted in the Selection.
SortOrder – Columns to sort by.
So, the variable selectionStringArgs used in the code from #TMSAL cannot use a value like "contact_id = 2700", because the parameter of CursorLoader SelectionArgs is not a filter but not "Parameters to be substituted in the Selection"
I hope this will help someone else too.

'System.Linq.IQueryable<NewsSite.Models.Domain.Tbl_News>' does not contain a definition

I Create A News Site With MVC5 But I Have Problem .
in Model i Create A Repository Folder And in this i Create Rep_Setting for
Connect to Tbl_Setting in DataBase .
public class Rep_Setting
{
DataBase db = new DataBase();
public Tbl_Setting Tools()
{
try
{
var qGetSetting = (from a in db.Tbl_Setting
select a).FirstOrDefault();
return qGetSetting;
}
catch (Exception)
{
return null;
}
}
}
And i Create a Rep_News for Main Page .
DataBase db = new DataBase();
Rep_Setting RSetting = new Rep_Setting();
public List<Tbl_News> GetNews()
{
try
{
List<Tbl_News> qGetNews = (from a in db.Tbl_News
where a.Type.Equals("News")
select a).OrderByDescending(s => s.ID).Skip(0).Take(RSetting.Tools().CountNewsInPage).ToList();
return qGetNews;
}
catch (Exception ex)
{
return null;
}
}
But This Code Have Error to Me
OrderByDescending(s=>s.ID).Skip(0).Take(RSetting.Tools().CountNewsInPage).ToList();
Error :
Error 18 'System.Linq.IQueryable<NewsSite.Models.Domain.Tbl_News>' does
not contain a definition for 'Take' and the best extension method overload
'System.Linq.Queryable.Take<TSource>(System.Linq.IQueryable<TSource>, int)' has
some invalid arguments
E:\MyProject\NewsSite\NewsSite\Models\Repository\Rep_News.cs 50 52 NewsSite
How i Resolve it ?
Try it this way. The plan of debugging is to split your execution, this also makes for a more reusable method in many cases. And a good idea is to avoid using null and nullables if you can, if you use them "on purpose" the you must have a plan for them.
DataBase db = new DataBase();
Rep_Setting RSetting = new Rep_Setting();
public List<Tbl_News> GetNews()
{
int skip = 0;
Tbl_Setting tools = RSetting.Tools();
if(tools == null){ throw new Exception("Found no rows in the database table Tbl_Setting"); }
int? take = tools.CountNewsInPage;//Nullable
if(!take.HasValue)
{
// Do you want to do something if its null maybe set it to 0 and not null
take = 0;
}
string typeStr = "News";
List<Tbl_News> qGetNews = (from a in db.Tbl_News
where a.Type.Equals(typeStr)
select a).OrderByDescending(s => s.ID).Skip(skip).Take(take.Value);
return qGetNews.ToList();
}
if qGetNews is a empty list you now don't break everything after trying to iterate on it, like your return null would. instead if returning null for a lit return a new List<>() instead, gives you a more resilient result.
So I said reusable method, its more like a single action. So you work it around to this. Now you have something really reusable.
public List<Tbl_News> GetNews(string typeStr, int take, int skip = 0)
{
List<Tbl_News> qGetNews = (from a in db.Tbl_News
where a.Type.Equals(typeStr)
select a).OrderByDescending(s => s.ID).Skip(skip).Take(take);
return qGetNews.ToList();
}
Infact you shjould always try to avoid returning null if you can.
public class Rep_Setting
{
DataBase db = new DataBase();
public Tbl_Setting Tools()
{
var qGetSetting = (from a in db.Tbl_Setting
select a).FirstOrDefault();
if(qGetSetting == null){ throw new Exception("Found no rows in the database table Tbl_Setting"); }
return qGetSetting;
}
}

sqlbulkcopy mem. management

I'm using SQLBULKCOPY to copy some data-tables into a database table, however, because the size of the files I'm copying run sometimes in excess of 600mb, I keep running out of memory.
I'm hoping to get some advice about managing the table size before I commit it to the database so I can free up some memory to continue writing.
Here are some examples of my code (some columns and rows eliminated for simplicity)
SqlBulkCopy sqlbulkCopy = new SqlBulkCopy(ServerConfiguration); //Define the Server Configuration
System.IO.StreamReader rdr = new System.IO.StreamReader(fileName);
Console.WriteLine("Counting number of lines...");
Console.WriteLine("{0}, Contains: {1} Lines", fileName, countLines(fileName));
DataTable dt = new DataTable();
sqlbulkCopy.DestinationTableName = "[dbo].[buy.com]"; //You need to define the target table name where the data will be copied
dt.Columns.Add("PROGRAMNAME");
dt.Columns.Add("PROGRAMURL");
dt.Columns.Add("CATALOGNAME");
string inputLine = "";
DataRow row; //Declare a row, which will be added to the above data table
while ((inputLine = rdr.ReadLine()) != null) //Read while the line is not null
{
i = 0;
string[] arr;
Console.Write("\rWriting Line: {0}", k);
arr = inputLine.Split('\t'); //splitting the line which was read by the stream reader object (tab delimited)
row = dt.NewRow();
row["PROGRAMNAME"] = arr[i++];
row["PROGRAMURL"] = arr[i++];
row["CATALOGNAME"] = arr[i++];
row["LASTUPDATED"] = arr[i++];
row["NAME"] = arr[i++];
dt.Rows.Add(row);
k++;
}
// Set the timeout, 600 secons (10 minutes) given table size--damn that's a lota hooch
sqlbulkCopy.BulkCopyTimeout = 600;
try
{
sqlbulkCopy.WriteToServer(dt);
}
catch (Exception e)
{
Console.WriteLine(e);
}
sqlbulkCopy.Close();//Release the resources
dt.Dispose();
Console.WriteLine("\nDB Table Written: \"{0}\" \n\n", sqlbulkCopy.DestinationTableName.ToString());
}
I continued to have problems getting SQLBulkCopy to work, and I realized I needed to do more work on each record before it was entered into the database, so I developed a simple LinQ to Sql method to do record by record updates, so I could edit other information and create more record information as it was being run,
Problem: This method's been running pretty slow (even on Core i3 machine), any ideas on how to speed it up (threading?) -- on a single processor core, with 1gb of memory it crashes or takes sometimes 6-8 hours to write the same amount of data as one SQLBulkCopy that takes a few moments. It does manage memory better though.
while ((inputLine = rdr.ReadLine()) != null) //Read while the line is not null
{
Console.Write("\rWriting Line: {0}", k);
string[] arr;
arr = inputLine.Split('\t');
/* items */
if (fileName.Contains(",,"))
{
Item = Table(arr);
table.tables.InsertOnSubmit(Item);
/* Check to see if the item is in the db */
bool exists = table.tables.Where(u => u.ProductID == Item.ProductID).Any();
/* Commit */
if (!exists)
{
try
{
table.SubmitChanges();
}
catch (Exception e)
{
Console.WriteLine(e);
// Make some adjustments.
// ...
// Try again.
table.SubmitChanges();
}
}
}
With helper method:
public static class extensionMethods
{
/// <summary>
/// Method that provides the T-SQL EXISTS call for any IQueryable (thus extending Linq).
/// </summary>
/// <remarks>Returns whether or not the predicate conditions exists at least one time.</remarks>
public static bool Exists<TSource>(this IQueryable<TSource> source, Expression<Func<TSource, bool>> predicate)
{
return source.Where(predicate).Any();
}
}
Try specifying the BatchSize property to 1000 which will batch up the insert in a 1000 record batch rather than the whole lot. You can tweak this value to find what is optimal. I have used sqlbulkcopy for similar size data and it works well.
Faced with the same issue, found that problem of OutOfMemory Exception was in DataTable.Rows maximum quantity limitations.
Solved with recreating table, with maximum 500000 rows limit.
Hope, my solution will be helpfull:
var myTable = new System.Data.DataTable();
myTable.Columns.Add("Guid", typeof(Guid));
myTable.Columns.Add("Name", typeof(string));
int counter = 0;
foreach (var row in rows)
{
++counter;
if (counter < 500000)
{
myTable.Rows.Add(
new object[]
{
row.Value.Guid,
row.Value.Name
});
}
else
{
using (var dbConnection = new SqlConnection("Source=localhost;..."))
{
dbConnection.Open();
using (var s = new SqlBulkCopy(dbConnection))
{
s.DestinationTableName = "MyTable";
foreach (var column in myTable.Columns)
s.ColumnMappings.Add(column.ToString(), column.ToString());
try
{
s.WriteToServer(myTable);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
s.Close();
}
}
}
myTable = new System.Data.DataTable();
myTable.Columns.Add("Guid", typeof(Guid));
myTable.Columns.Add("Name", typeof(string));
myTable.Rows.Add(
new object[]
{
row.Value.Guid,
row.Value.Name
});
counter = 0;
}
}

Blackberry - How to get Field Labels from PIMItem

How can we get Field Labels from PIMItem. The following code is with PIMList
String label = pimList.getAttributeLabel(
blackBerryContact.getAttributes(Contact.TEL, i));
But i have PIMItem. There is a method PIMItem.getPIMList() which returns null for me in the code below. THE API at http://www.blackberry.com/developers/docs/5.0.0api/index.html says "getPIMList()
Gets the PIMList associated with this item." Below is sample code that i am trying to achive -
// Load the address Book and allow the user to select a contact
BlackBerryContactList contactList = (BlackBerryContactList)
PIM.getInstance().openPIMList(PIM.CONTACT_LIST,PIM.READ_ONLY);
PIMItem userSelectedContact = contactList.choose();
// Now get the Field labels for contact numbers for userSelectedContact
class Scr extends MainScreen {
Scr() {
}
protected void makeMenu(Menu menu, int instance) {
super.makeMenu(menu, instance);
menu.add(new MenuItem("add label", 1, 1){public void run() {
try {
BlackBerryContactList contactList =
(BlackBerryContactList) PIM.getInstance().openPIMList(
PIM.CONTACT_LIST, PIM.READ_ONLY);
BlackBerryContact contact =
(BlackBerryContact) contactList.choose();
add(new LabelField(getContactInfo(contact)));
} catch (PIMException e) {
e.printStackTrace();
}
}});
}
String getContactInfo(BlackBerryContact c) {
StringBuffer result = new StringBuffer();
result.append("Name: ");
result.append(c.getStringArray(
BlackBerryContact.NAME, 0)[BlackBerryContact.NAME_GIVEN]);
result.append(" ");
result.append(c.getStringArray(
BlackBerryContact.NAME, 0)[BlackBerryContact.NAME_FAMILY]);
result.append("Email: ");
result.append("\n");
result.append(c.getString(
BlackBerryContact.EMAIL, BlackBerryContact.ATTR_NONE));
return result.toString();
}
}
Thanks Max for the response. The returning NULL issue was problem with my code which i have rectified. I was also able to get Labels for Fields, but the loop retrieves only fields that the Contact has on his card.
I am looking to get all the 8 labels that Contact.TEL has -
Int maxAllowed = contactList.maxValues(Contact.TEL); // Gives me 8
All the 8 Labels might not be in use in for a user, For e.g a user might have WORK, WORK2, HOME, HOME2 and MOBILE. Others FAX, PAGER and OTHER might not be filled i want to get all the allowed labels and update a given number for the one that is empty.
How can we check and update the following
Contact.ATTR_PAGER, Contact.ATTR_FAX, Contact.ATTR_OTHER
Please let me know if the explanation is not clear, or some more details are required.
BlackBerryContactList contactList = (BlackBerryContactList)
PIM.getInstance().openPIMList(PIM.CONTACT_LIST,PIM.READ_WRITE);
PIMItem pimItem = contactList.choose();
BlackBerryContact blackBerryContact = (BlackBerryContact)pimItem;
PIMList pimList = blackBerryContact.getPIMList();
// To get Labels
int phoneCount = blackBerryContact.countValues(BlackBerryContact.TEL);
String[] phoneNumbers = new String[phoneCount];
String[] labels = new String[phoneCount];
for (int i = 0; i > phoneCount; i++) {
String phoneNumber = blackBerryContact.getString(Contact.TEL, i);
String label = pimList.getAttributeLabel(
blackBerryContact.getAttributes(Contact.TEL, i));
//Add the number and label to the array.
phoneNumbers[i] = phoneNumber;
labels[i] = label + ":" + phoneNumber;
}

Resources