Hallo liebe Forumsmitglieder,
suche jetzt schon Tage nach einer Lösung für meine Xamarin App die ich mit Visual Studio erstelle.
Die Dokumentation von Microsoft ist leider in diesem Bereich unvollständig.
Was ich hinbekomme ist folgendes: Sqlite Datenbank erstellen. Daten in Listview hinzufügen ,anzeigen, löschen usw.
Das ganze hört auf wenn ich die Daten aus Sqlite weiterverarbeiten möchte.
Abfragen in einen ListView anzeigen das funktioniert alles soweit. Nur ich bekomme die Daten einfach nicht zurück als String.
Was möchte ich erreichen?
z.B nach der ID 200 in der Datenbank suchen.
Von ID 200 den Vornamen in ein DisplayAlert auf dem Smartphone anzeigen.
Was bekomme ich momentan:
Leider nicht den Vornamen sondern nur folgenden Text:
System.Threading.Tasks.Task1[System.Collections.Generic.List
1[Projekt.Models.Person]]
Hier mein Code
Database.cs
public class Database
{
readonly SQLiteAsyncConnection _database;
public Database(string dbPath)
{
_database = new SQLiteAsyncConnection(dbPath);
_database.CreateTableAsync<Person>().Wait();
}
public Task GetVornameAsync(int id)
{
return = _database.QueryAsync<Person>("SELECT Vorname FROM person WHERE ID ="+id);
}
Person.cs
using System;
using System.Collections.Generic;
using System.Text;
using SQLite;
namespace Test.Models
{
[Table("person")]
public class Person
{
[PrimaryKey, AutoIncrement]
public int ID { get; set; }
[MaxLength(250), Unique]
public string SqlID { get; set; }
[MaxLength(250)]
public string Vorname { get; set; }
[MaxLength(250)]
public string Nachname { get; set; }
[MaxLength(250)]
public string Passwort { get; set; }
public bool Passwort_Speichern { get; set; }
public bool Admin { get; set; }
public DateTime Letzte_Aktualisierung { get; set; }
public int Urlaub_Jahr { get; set; }
public int Urlaub_Vorjahr { get; set; }
public int Urlaub_Genommen { get; set; }
public int Urlaub_Rest { get; set; }
public int Ueberstunden { get; set; }
}
}
page.xaml.cs
private async void LoginButton(object sender, EventArgs e)
{
var ausgabe = App.Database.GetVornameAsync(200);
string ausgabe2 = ausgabe.ToString();
_ = DisplayAlert("Info", ausgabe2, "OK");
}
App.xaml.cs
public partial class App : Application
{
static Database database;
public static Database Database
{
get
{
if (database == null)
{
database = new Database(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "test.db3"));
}
return database;
}
}
Ich hoffe mir kann endlich einer weiter helfen!
Viele Grüße
Christoph
Hallo,
deine GetVornameAsync Methode gibt den Task zurück. Es fehlt mindestens ein await, entweder in der Methode oder beim Aufruf dieser.
glandorf
Hallo und willkommen,
da ist noch einiges falsch an der Implementierung und Benutzung deiner GetVornameAsync
-Methode:
await
(außerdem muß dann die Methode auch als async
deklariert werden)QueryAsync<T>
ist Task<List<T>
(s.a. direkt im Code von SQLiteAsync.cs) - du gibst aber nur die nicht-generische Basisklasse Task
zurück.var
(bei var ausgabe = App.Database.GetVornameAsync(200);
) gehst, sollte dir als Tooltip der statische Typ Task
ausgegeben werden.QueryAsync<T>
eine List<T>
zurückgibt (und nicht nur einen einzelnen Datensatz, da die Methode ja für beliebige Queries ist), mußt du noch z.B. mittels Linq weitere Methoden aufrufen (z.B. FirstOrDefault()
).await
auf den Rückgabewert warten.So ich hoffe, dies gibt dir genügend Hinweise (und auch Ermutigung zum Nachschlagen der Stichworte), so daß du den Code alleine implementieren kannst.
Und noch ein paar weitere Seiten zur Benutzung von SQLiteAsync
:
Adding SQLite to my Xamarin forms application
Xamarin.Tips – Super Simple Sqlite
Xamarin: Efficiently Using a SQLite Database (schon etwas anspruchsvoller)
Vielen Dank schon einmal für die Hilfe.
Dennoch komme ich einfach nicht auf die richtige Lösung. Habe jetzt auch wieder alle Varianten durch ob mit Linq oder Query, Asyncron oder nicht, irgendwas klappt nicht.
Habe den Code folgendermaßen geändert:
page.xaml.cs
private async void LoginButton(object sender, EventArgs e)
{
var ausgabe = await App.Database.GetVornameAsync(200);
string ausgabe2 = ausgabe.ToString();
_ = DisplayAlert("Info", ausgabe2, "OK");
}
Database.cs
public async Task<Person> GetVornameAsync(int id)
{
var v = await _database.QueryAsync<Person>("SELECT Vorname FROM person WHERE ID =" + id);
var v2 = v.FirstOrDefault();
return v2;
}
Nehme ich
Task<List<Person>>
dann funktioniert wieder die FirstOrDefault() Methoden nicht.
Bekomme momentan folgenden Fehler "System.NullReferenceException: 'Object reference not set to an instance of an object"
Rufe ich die App.Database.GetVornameAsync(200) Methode ohne await auf, so habe ich zwar keinen Fehler aber wieder im DisplayAlert
folgenden Text stehen: "System.Threading.Tasks.Task1[System.Collections.Generic.List
1[Projekt.Models.Person]]"
Ich hoffe einer hat noch einen Tipp für mich.
Schönes Wochenende
Christoph
Du hast das mit Sqlite-Net anscheinend überhaupt nicht erlesen und probierst einfach so ins blaue herum.
Das QueryAsync liefert dir eine List<Person>, wobei in den objecten in deinem Fall nur der Vorname gesetzt ist.
Ganz abgesehen davon das du [Artikelserie] SQL: Parameter von Befehlen nicht beachtest, ist es doch recht einfach, wenn du mal die Doku lesen würdest.
public async Task<Person> GetVornameAsync(int id)
{
var person = await _database.Table<Person>.Where(p=>p.ID==id).FirstOrDefault();
return person;
}
private async void LoginButton(object sender, EventArgs e)
{
var person = await App.Database.GetVornameAsync(200);
if(person!= null)
{
_ = DisplayAlert("Info", person.Vorname, "OK");
}
else
{
_ = DisplayAlert("Info", "ID not found", "OK");
}
}
Du solltest dir nochmal anschauen, wie Tasks und async/await funktionieren.
Deine benötigte Lösung ist banal einfach, wenn man du verstehst, wie du async/await und Tasks verwenden musst!
Du bekommst von deiner Methode den Task<Person> zurück.
Durch das await, wird auf den Task gewartet und dir direkt Person geliefert.
Dadurch kannst du direkt auf den Vorname zugreifen.
Person person = await App.Database.GetVornameAsync(200);
_ = DisplayAlert("Info", person.Vorname, "OK");
Nachtrag:
Du solltest die Methode nicht GetVornameAsync nennen, da du keinen Vornamen sondern die ganze Person lieferst.
Am besten nennst du die Methode allgemeiner wie z.B. LoadPerson!
Nachtrag 2:
Du solltest dann aber auch darauf achten, dass Person bei ungültigen IDs null sein kann.
Nachtrag 3:
FZelle war schneller 🙁
T-Virus
Developer, Developer, Developer, Developer....
99 little bugs in the code, 99 little bugs. Take one down, patch it around, 117 little bugs in the code.
Vielen lieben Dank für eure Hilfe!
Jetzt funktioniert es.
Es war allerdings hier noch ein Fehler:
public async Task<Person> GetVornameAsync(int id)
{
var person = await _database.Table<Person>.Where(p=>p.ID==id).FirstOrDefault();
return person;
}
Und so funktioniert es:
public async Task<Person> GetPersonAsync(int id)
{
var person = await _database.Table<Person>().FirstOrDefaultAsync(p => p.ID == id);
return person;
}
Ich hatte die ganze Zeit einen falschen Ansatzpunkt verfolgt.
Angenehmes Wochenende wünsche ich noch!
Christoph