Xamarin.Android SQLite.NET - c#

I want to make a application which show record from database, and I can add new record. I first time use a database in C# so I have completely nobie in this topic. When I click button Accept, than compilator show "An unhandled exception occured.". I don't know what I'm doing wrong.
My code:
public class Person
{
[PrimaryKey, AutoIncrement]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Address { get; set; }
public string CellPhoneNumber { get; set; }
public string EMailAddress { get; set; }
public Person() { }
public Person(string firstName, string lastName, string address, string cellPhoneNumber, string eMailAddress)
{
FirstName = firstName;
LastName = lastName;
Address = address;
CellPhoneNumber = cellPhoneNumber;
EMailAddress = eMailAddress;
}
}
public class PersonDatabase
{
public SQLiteConnection connection;
static string baseName = "Person.db";
static string basePath = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
static string path = Path.Combine(basePath, baseName);
public PersonDatabase()
{
// If database don't exist then, will created new file. Else open exist file.
if (!File.Exists(path))
{
connection = new SQLiteConnection(path);
connection.CreateTable<Person>();
}
connection = new SQLiteConnection(path);
}
public PersonDatabase(Person person) : base()
{
//person.Id = connection.Table<Person>().Count() + 1;
connection.Insert(person);
connection.Update(person);
}
}
public class MainActivity : Activity
{
public PersonDatabase database = new PersonDatabase();
private List<Person> personList = new List<Person>();
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
var addButton = FindViewById<Button>(Resource.Id.addButton);
var query = database.connection.Table<Person>();
foreach (var person in query)
{
personList.Add(person);
}
var listView = FindViewById<ListView>(Resource.Id.listView);
listView.Adapter = new ListViewAdapter(this, personList);
addButton.Click += (object sender, EventArgs e) =>
{
StartActivity(typeof(FormActivity));
};
}
}
[Activity(Label = "FormActivity")]
public class FormActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Form);
var firstName = FindViewById<EditText>(Resource.Id.editTextFirstName);
var lastName = FindViewById<EditText>(Resource.Id.editTextLastName);
var address = FindViewById<EditText>(Resource.Id.editTextAddress);
var cellPhoneNumber = FindViewById<EditText>(Resource.Id.editTextCellNumber);
var eMailAddress = FindViewById<EditText>(Resource.Id.editTextMail);
var acceptButton = FindViewById<Button>(Resource.Id.acceptButton);
acceptButton.Click += (object sender, EventArgs e) =>
{
Person newPerson = new Person(firstName.Text, lastName.Text, address.Text, cellPhoneNumber.Text, eMailAddress.Text);
var personDatabase = new PersonDatabase(newPerson);
StartActivity(typeof(MainActivity));
Finish();
};
}
}

Related

C# Deleting a customer from its ID

Hi there I was wondering if its possible for me to create a method in my customer.cs to delete a customer depending on its ID. How I want this to work is that the user will select a customer from the list box which only shows the customers firstName and then hit delete which will delete the customer off the list box. But I want to somehow create a method in the customer.cs which will look at the ID then delete it if its the right one. Can this be done? Any help would be create thank you.
form.cs:
public partial class AddCustomer : Form
{
List<Customer> list = new List<Customer>();
Random rand = new Random();
public AddCustomer()
{
InitializeComponent();
}
// Adds Customer
private void buttonAddCustomer_Click(object sender, EventArgs e)
{
Customer customer = new Customer();
customer.customerId = rand.Next();
customer.firstName = textBoxfn.Text;
list.Add(customer);
listBoxCustomers.Items.Add(customer.firstName);
}
// Deletes Customer
private void buttonDeleteCustomer_Click(object sender, EventArgs e)
{
listBoxCustomers.Items.Remove(listBoxCustomers.SelectedItem);
}
}
}
Customer.cs:
public class Customer
{
public int customerId;
public string firstName;
public string lastName;
public string phoneNumber;
public string address;
public string FirstName
{
get { return firstName; }
set { firstName = value; }
}
public string LastName
{
get { return lastName; }
set { lastName = value; }
}
public string PhoneNumber
{
get { return phoneNumber; }
set { phoneNumber = value; }
}
public string Address
{
get { return address; }
set { address = value; }
}
}
}
One idea is to load your customer list into a BindingList<Customer>
Now with this approach you work from the BindingList and the selected index of the ListBox.
I used a pre-defined customer class I had.
public class Customer
{
public int CustomerIdentifier { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Street { get; set; }
public string City { get; set; }
public string PostalCode { get; set; }
public int CountryIdentifier { get; set; }
public override string ToString() => $"{FirstName} {LastName}";
}
Mocked data
public class MockedData
{
public static List<Customer> Customers() => new List<Customer>()
{
new Customer()
{
CustomerIdentifier = 1, FirstName = "Jim", LastName = "Adams",
Street = "120 Hanover Sq.", City = "London", PostalCode = "WA1 1DP",
CountryIdentifier = 19
},
new Customer()
{
CustomerIdentifier = 2, FirstName = "Mary", LastName = "Adams",
Street = "1 rue Alsace-Lorraine", City = "Toulouse", PostalCode = "31000",
CountryIdentifier = 8
},
new Customer()
{
CustomerIdentifier = 3, FirstName = "Karen", LastName = "White",
Street = "120 Hanover Sq.", City = "London", PostalCode = "WA1 1DP",
CountryIdentifier = 19
}
};
}
Form code
public partial class Form1 : Form
{
private readonly BindingList<Customer> _customersBindingList;
public Form1()
{
InitializeComponent();
_customersBindingList = new BindingList<Customer>(MockedData.Customers());
listBoxCustomers.DataSource = _customersBindingList;
}
private void RemoveCurrentButton_Click(object sender, EventArgs e)
{
if (listBoxCustomers.SelectedIndex > -1)
{
_customersBindingList.RemoveAt(listBoxCustomers.SelectedIndex);
}
RemoveCurrentButton.Enabled = listBoxCustomers.SelectedIndex > -1;
}
}
Here is the function to remove all customers with a certain id :
private void RemoveCustomer(int id)
{
list.RemoveAll(c => c.customerId == id);
}

Xamarin Android C#: Populate ListView Custom Row With Data From SQLite Database

I'm tring to create a ListView which is fed data from an SQLite Database (pre-existing db file). The ListView uses a custom row which is one of the aspects which baffle me; How do I extract the data and then assign it to a TextView in the custom row?
I'm new to Xamarin, so would really appreciate any guidance you can give me on this, Thank you!
Current Dialog Box Error When Run:
Java.Lang.ClassNotFoundException: Didn't find class "md5c4f65b5cf99ab8e97737acf0f8ec7efd.DBHelper" on path: DexPathList[[zip file "/data/app/AppName.Droid-1/base.apk"],nativeLibraryDirectories=[/data/app/AppName.Droid-1/lib/arm, /system/fake-libs, /data/app/AppName.Droid-1/base.apk!/lib/armeabi-v7a, /system/lib, /vendor/lib]]
'MainActivity':
public class EateriesActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
Title = "Find An Eatery";
SetContentView(Resource.Layout.Eateries);
DBHelper db = new DBHelper();
db.CreateDatabase();
db.CreateTable();
var items = db.GetData();
var listView = FindViewById<ListView>(Resource.Id.EateryList_ListView);
listView.Adapter = new ArrayAdapter<string>(this, Resource.Layout.Eatery_ListView_Row, items);
}
}
ListViewAdapter (is this necessary?):
class ListViewAdapter : BaseAdapter<Eatery>
{
private List<Eatery> myItems;
private Context myContext;
public ListViewAdapter(Context context, List<Eatery> items)
{
myItems = items;
myContext = context;
}
public override int Count
{
get { return myItems.Count; }
}
public override long GetItemId(int position)
{
return position;
}
public override Eatery this[int position]
{
get
{
return myItems[position];
}
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
View row = convertView;
if (row == null)
{
row = LayoutInflater.From(myContext).Inflate(Resource.Layout.Eatery_ListView_Row, null, false);
}
TextView placeName = row.FindViewById<TextView>(Resource.Id.placeName);
placeName.Text = myItems[position].Name;
TextView placeTown = row.FindViewById<TextView>(Resource.Id.placeTown);
placeTown.Text = myItems[position].Town;
return row;
}
}
Eatery:
public class Eatery
{
[PrimaryKey]
public string ID { get; set; }
public string Image { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Address1 { get; set; }
public string Town { get; set; }
public string PostCode { get; set; }
public string Cuisine { get; set; }
}
DBHelper:
public class DBHelper
{
private static string DB_PATH = System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal);
private static string DB_NAME = "EateryDB.db";
public void CreateDatabase()
{
string dbPath = Path.Combine(DB_PATH, DB_NAME);
var db = new SQLiteConnection(new SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid(), dbPath);
}
public void CreateTable()
{
string dbPath = Path.Combine(DB_PATH, DB_NAME);
var db = new SQLiteConnection(new SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid(), dbPath);
db.CreateTable<Eatery>();
}
public List<string> GetData()
{
string dbPath = Path.Combine(DB_PATH, DB_NAME);
var db = new SQLiteConnection(new SQLite.Net.Platform.XamarinAndroid.SQLitePlatformAndroid(), dbPath);
List<string> data = new List<string>();
foreach (var item in db.Table<Eatery>())
{
var place = item.Name.ToString(); item.Town.ToString();
data.Add(place);
}
return data;
}
Based on your two version of code, I think what you need is adding data from your database to the myItems.
Then you can for example code like this:
List<Eatery> data = new List<Eatery>();
foreach (var item in db.Table<Eatery>())
{
var place = item.Name.ToString();
var location = item.Location.ToString();
var rating = item.Rating;
item.Town.ToString();
data.Add(new Eatery() { PlaceName = place, PlaceLocation = location, PlaceRating = rating });
}
And finally add this data to your adapter as you did when you hard code:
MyListViewAdapter adapter = new MyListViewAdapter(this, data);

Binding combobox BindingList Winforms C#

Ok, so I have been facing this issue several times now but I always seemed to figure it out.
This time, ive been stuck and ive tried multiple things, but nothing is working.
I have a combobox of customers in a customer form. When i create a new customer, my combobox is not updating. It only refreshes when closing and re-opening the form.
I am aware of the "ugly and quick" solutions, but I don't want to use this unless I have no other choise. So ive been using BindingLists because of the events... BUT this is not working in my case.
Ive been staring to this for a time now, let it aside, tried again, but keep on failing.
Does anyone know whats missing in this puzzle?
Now the code: Presenter
public class CustomerPresenter
{
private tbl_customer customer = new tbl_customer();
private CustomerView customerView = new CustomerView();
public CustomerPresenter(tbl_customer customer, CustomerView customerView)
{
this.customer = customer;
this.customerView = customerView;
customerView.customerPresenter = this;
}
// Get a list of customers
public List<tbl_customer> customerList;
public BindingList<tbl_customer> getCustomers()
{
using (var customers = new DBCrownfishEntities())
{
var customer = from c in customers.tbl_customer
where c.IsDeleted == false
select c;
this.customerList = customer.ToList();
var listBinding = new BindingList<tbl_customer>(this.customerList);
return listBinding;
}
}
public void testAdd()
{
tbl_customer customer = new tbl_customer();
customer.CustomerPrefix = "Pref";
customer.CustomerName = "Name";
customer.CustomerAddress = "Address";
customer.CustomerPostalCode = "1111";
customer.CustomerCity = "City";
customer.CustomerCountry = "Country";
customer.CustomerCountryCode = "BE";
customer.CustomerVat = "123456789";
customer.hasVatNumber = true;
try
{
using (var cust = new DBCrownfishEntities())
{
cust.tbl_customer.Add(customer);
cust.SaveChanges();
MessageBox.Show("A new customer is succesfully added!");
}
}
catch (EntityException exception)
{
MessageBox.Show(exception.InnerException.Message.ToString(), "Error Connecting database");
}
catch (Exception)
{
throw;
}
}
}
View:
BindingSource bsCustomers = new BindingSource();
private void CustomerView_Load(object sender, EventArgs e)
{
bsCustomers.DataSource = customerPresenter.getCustomers();
cbCustomers.DataSource = bsCustomers;
cbCustomers.DisplayMember = "CustomerName";
cbCustomers.ValueMember = "CustomerId";
radioButton1_CheckedChanged(null, null);
}
private void button1_Click_1(object sender, EventArgs e)
{
customerPresenter.testAdd();
}
Model:
public partial class tbl_customer
{
public tbl_customer()
{
this.tbl_invoices = new HashSet<tbl_invoices>();
}
public int CustomerID { get; set; }
public string CustomerPrefix { get; set; }
public string CustomerName { get; set; }
public string CustomerEmailaddress { get; set; }
public string CustomerAddress { get; set; }
public string CustomerPostalCode { get; set; }
public string CustomerCity { get; set; }
public string CustomerVat { get; set; }
public string CustomerCountryCode { get; set; }
public string CustomerCountry { get; set; }
public bool IsDeleted { get; set; }
public bool hasVatNumber { get; set; }
public virtual ICollection<tbl_invoices> tbl_invoices { get; set; }
}

Can't read data from second table using Azure Mobile Services .NET

I created a new table "TravauxDBs" using Visual Studio, but when i call PullAsync it returns count = 0, so i guess it's empty. Then i get an error "not found".
Everything works fine using basic table ToDoItems, and i use the same code for this new table.
My item mobile side :
public class TravauxDB
{
public string Id { get; set; }
[JsonProperty(PropertyName = "nomtravail")]
public string NomTravail { get; set; }
[JsonProperty(PropertyName = "voie")]
public string Voie { get; set; }
[JsonProperty(PropertyName = "pk")]
public string PK { get; set; }
[JsonProperty(PropertyName = "quantity")]
public string Quantity { get; set; }
[JsonProperty(PropertyName = "unite")]
public string Unite { get; set; }
[JsonProperty(PropertyName = "observation")]
public string Observation { get; set; }
[JsonProperty(PropertyName = "idchantier")]
public string IdChantier { get; set; }
}
Service side :
public class TravauxDB : EntityData
{
public string NomTravail { get; set; }
public string Voie { get; set; }
public string PK { get; set; }
public string Quantity { get; set; }
public string Unite { get; set; }
public string Observation { get; set; }
public string IdChantier { get; set; }
}
Activity :
public class Travaux : ActionBarActivity
{
private Android.Support.V7.Widget.SearchView _searchView3;
private ListView _listView3;
private ArrayAdapter _adapter3;
private MobileServiceClient client;
private IMobileServiceSyncTable<TravauxDB> TravauxTable;
const string applicationURL = #"myurl";
const string applicationKey = #"mykey";
const string localDbFilename = "localstore.db";
public List<string> travaux { get; private set; }
protected override async void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.Layout_travaux);
CurrentPlatform.Init();
client = new MobileServiceClient(applicationURL, applicationKey);
await InitLocalStoreAsync();
TravauxTable = client.GetSyncTable<TravauxDB>();
await SyncAsync();
List<string> travaux = await ItemsOnly();
_listView3 = FindViewById<ListView>(Resource.Id.listView3);
_adapter3 = new ArrayAdapter<string>(this, Android.Resource.Layout.SimpleListItem1, travaux);
_listView3.Adapter = _adapter3;
_listView3.ItemClick += _listView3_ItemClick;
}
void _listView3_ItemClick(object sender, AdapterView.ItemClickEventArgs e)
{
int pos = e.Position;
Intent b = new Intent(this, typeof(Travail));
Bundle bundle = new Bundle();
bundle.PutInt("Ntravail", pos);
b.PutExtras(bundle);
StartActivity(b);
}
public override bool OnCreateOptionsMenu(IMenu menu)
{
MenuInflater.Inflate(Resource.Menu.main, menu);
var item = menu.FindItem(Resource.Id.action_search);
var searchItem = MenuItemCompat.GetActionView(item);
_searchView3 = searchItem.JavaCast<Android.Support.V7.Widget.SearchView>();
_searchView3.QueryTextChange += (s, e) => _adapter3.Filter.InvokeFilter(e.NewText);
_searchView3.QueryTextSubmit += (s, e) =>
{
Toast.MakeText(this, "Searched for: " + e.Query, ToastLength.Short).Show();
e.Handled = true;
};
return true;
}
private void CreateAndShowDialog(Exception exception, String title)
{
CreateAndShowDialog(exception.Message, title);
}
private void CreateAndShowDialog(string message, string title)
{
Android.App.AlertDialog.Builder builder = new Android.App.AlertDialog.Builder(this);
builder.SetMessage(message);
builder.SetTitle(title);
builder.Create().Show();
}
private async Task InitLocalStoreAsync()
{
string path = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), localDbFilename);
if (!File.Exists(path))
{
File.Create(path).Dispose();
}
var store = new MobileServiceSQLiteStore(path);
store.DefineTable<TravauxDB>();
await client.SyncContext.InitializeAsync(store);
}
private async Task SyncAsync()
{
try
{
await client.SyncContext.PushAsync();
await TravauxTable.PullAsync("alltravaux", TravauxTable.CreateQuery()); // query ID is used for incremental sync
}
catch (Java.Net.MalformedURLException)
{
CreateAndShowDialog(new Exception("There was an error creating the Mobile Service. Verify the URL"), "Error");
}
catch (Exception e)
{
CreateAndShowDialog(e, "Error");
}
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
AuthenticationAgentContinuationHelper.SetAuthenticationAgentContinuationEventArgs(requestCode, resultCode, data);
}
public async Task<List<string>> ItemsOnly()
{
try
{
List<string> travaux = await TravauxTable
.Select(tr => tr.NomTravail).ToListAsync();
return travaux;
}
catch (MobileServiceInvalidOperationException e)
{
Console.Error.WriteLine(#"ERROR {0}", e.Message);
return null;
}
}
I also added a new controller for this, just replaced ToDoItem by TravauxDB :
public class TravauxController : TableController<TravauxDB>
{
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
ChantierContext context = new ChantierContext();
DomainManager = new EntityDomainManager<TravauxDB>(context, Request, Services);
}
// GET tables/TodoItem
public IQueryable<TravauxDB> GetAllTravauxDB()
{
return Query();
}
// GET tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
public SingleResult<TravauxDB> GetTravauxDB(string id)
{
return Lookup(id);
}
// PATCH tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
public Task<TravauxDB> PatchTravauxDB(string id, Delta<TravauxDB> patch)
{
return UpdateAsync(id, patch);
}
// POST tables/TodoItem
public async Task<IHttpActionResult> PostTravauxDB(TravauxDB item)
{
TravauxDB current = await InsertAsync(item);
return CreatedAtRoute("Tables", new { id = current.Id }, current);
}
// DELETE tables/TodoItem/48D68C86-6EA6-4C25-AA33-223FC9A27959
public Task DeleteTravauxDB(string id)
{
return DeleteAsync(id);
}
}
If something is missing or you need more details let me know.
Thank you by advance.
The client class name needs to match the server controller name. So, your class should be called Travaux instead of TravauxDB. Alternatively, you can use the attribute [TableName] on the class.

Getting StackOverflowException in connecting list to listbox

I have created class Auction.cs with this code behind :
namespace WebApplication5
{
public class Auction
{
public string Productname { get; set; }
public string Lastbidder { get; set; }
public int Bidvalue { get; set; }
private List<Auction> listaAukcija = new List<Auction>();
public List<Auction> ListaAukcija
{
get { return listaAukcija; }
set { listaAukcija = value; }
}
public void getAll()
{
using (SqlConnection conn = new SqlConnection(#"data source=JOVAN-PC;database=aukcija_jovan_gajic;integrated security=true;"))
{
SqlCommand cmd = conn.CreateCommand();
cmd.CommandText = #"SELECT a.id AS aid, p.name AS pn, u.name AS un, a.lastbid AS alb FROM (Auction a INNER JOIN Product p ON a.productid = p.id) INNER JOIN User u ON a.lastbider = u.id";
conn.Open();
using (SqlDataReader reader = cmd.ExecuteReader())
{
listaAukcija.Clear();
while (reader.Read())
{
Auction auction = new Auction();
if (reader["aid"] as int? != null)
{
auction.Productname = reader["pn"] as string;
auction.Lastbidder = reader["un"] as string;
auction.Bidvalue = (int)reader["alb"];
}
listaAukcija.Add(auction);
}
}
}
}
public override string ToString()
{
return base.ToString();
}
}
}
I called it's methods in another class called DbBroker.cs :
public class DbBroker : Home
{
Auction aukcija = new Auction();
public void executeQuery()
{
aukcija.getAll();
}
public void getArr()
{
List<string[]> lista = aukcija.ListaAukcija.Cast<string[]>().ToList();
var x = ListBox1.Text;
x = lista.ToString();
}
}
And called getArr on Home page :
public partial class Home : System.Web.UI.Page
{
DbBroker dbb = new DbBroker();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Label3.Text = Session["Username"].ToString();
dbb.getArr();
}
}
}
The problem is, I get StackOverflowException error on Auction aukcija = new Auction(); in DbBroker.cs class. I don't know why or how to solve it.
You are creating a list of Auctions objects within itself = Stackoverflow.
This is your problem:
public class Auction {
private List<Auction> listaAukcija = new List<Auction>();
}
You will need to separate the Auction model from the service or repository that gets the data.
For example:
//the model
public class Auction {
public string Productname { get; set; }
public string Lastbidder { get; set; }
public int Bidvalue { get; set; }
public override string ToString()
{
return base.ToString();
}
}
//the service (or can replace this with a repository)
public class AuctionService {
private List<Auction> listaAukcija = new List<Auction>();
public List<Auction> ListaAukcija
{
get { return listaAukcija; }
set { listaAukcija = value; }
}
public void getAll()
{
//get the data and populate the list
}
}
UPDATE
You will need to instantiate the AuctionService in DbBroker. DbBroker does not inherit Home anymore (commented out).
public class DbBroker //: Home <-- circular reference
{
AuctionService auctionService = new AuctionService();
public void executeQuery()
{
auctionService.getAll();
}
public void getArr()
{
string[] lista = auctionService.ListaAukcija.ConvertAll(obj => obj.ToString()).ToArray();
ListBox1.Text = string.Join("\n", lista);
}
}
and on Page_Load() - you did not call executeQuery() function to populate the list.
public partial class Home : System.Web.UI.Page
{
DbBroker dbb = new DbBroker();
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
Label3.Text = Session["Username"].ToString();
dbb.executeQuery(); //populate list.
dbb.getArr(); //convert to string and update textbox
}
}
}
PS. With the new update, AuctionService should actually be the repository, and DbBroker can act as the Service layer. However, this still works for educational purposes.
I hope this helps.

Categories

Resources