habe mir die Doku zu async und await angesehen und auch bereits angewendet bzw. nachvollzogen.
Habe hierzu noch eine Frage. Du sagst ja ich soll immer die async Methoden verwenden, als z.b. so:
private static async void UseCase_QueryTypesAsync(DataContext dbContext)
{
// nur zur Demonstration ein kleines View, hier brauch man keine Migration
var result = await dbContext.VW_Test.ToListAsync();
Console.WriteLine(string.Join("\n", result));
}
Aber was bringt es in diesem Fall? Hier wird doch sowieso nur der eine Aufruf gemacht? Oder ist dann die Methode ToListAsync an sich schon schneller?
Edit: Habe es gerade mal mit der Klasse Stopwatch gemessen (jeweils 5-6 mal). Ich brauche mit async und await im Schnitt 0,2 Sekunden länger.
Ich habe den Fehler gefunden. Das View ist jedes mal verschwunden wenn man im DB Browser die Verbindung schließt und wieder öffnet. Hier muss man noch den Button "Änderungen schreiben" nutzen, erst dann existiert das View tatsächlich. Vorher kann man aber schon via SQL in dem Tool damit Abfragen generieren. Sorry, ich arbeite erst jetzt mit diesem Tool und hab es nicht bemerkt. Danke für deine Hilfe.
Ne, es gibt nur eine DB. Ich habe den ConnectionString zur besseren Lesbarkeit immer gekürzt, der geht definitiv auf die richtige DB. Und es gibt nur einen Context. Ich gehe davon aus das Sqlite evtl. das nicht unterstützt. Habe bei Google auch nichts gefunden.
Mit Raw Sql kommt der selbe Fehler "no such table".
dbContext.VW_Test.FromSqlRaw(@"select * from VW_Test").ToList()
Das Thema Logging wurde in meinem Tutorial erst jetzt behandelt. Hier spuckt die Console nun folgendes aus:
Fehler
info: Microsoft.EntityFrameworkCore.Infrastructure[10403]
Entity Framework Core 5.0.1 initialized 'DataContext' using provider 'Microsoft.EntityFrameworkCore.Sqlite' with options: None
fail: Microsoft.EntityFrameworkCore.Database.Command[20102]
Failed executing DbCommand (10ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT "v"."Nachname", "v"."Vorname"
FROM "VW_Test" AS "v"
fail: Microsoft.EntityFrameworkCore.Query[10100]
An exception occurred while iterating over the results of a query for context type 'Beispielanwendung_Einfach.DataContext'.
Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'no such table: VW_Test'.
at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db)
at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements(Stopwatch timer)+MoveNext()
at Microsoft.Data.Sqlite.SqliteCommand.GetStatements(Stopwatch timer)+MoveNext()
at Microsoft.Data.Sqlite.SqliteDataReader.NextResult()
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior)
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.ExecuteReader()
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(DbContext _, Boolean result)
at Microsoft.EntityFrameworkCore.Storage.NonRetryingExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
Microsoft.Data.Sqlite.SqliteException (0x80004005): SQLite Error 1: 'no such table: VW_Test'.
at Microsoft.Data.Sqlite.SqliteException.ThrowExceptionForRC(Int32 rc, sqlite3 db)
at Microsoft.Data.Sqlite.SqliteCommand.PrepareAndEnumerateStatements(Stopwatch timer)+MoveNext()
at Microsoft.Data.Sqlite.SqliteCommand.GetStatements(Stopwatch timer)+MoveNext()
at Microsoft.Data.Sqlite.SqliteDataReader.NextResult()
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteReader(CommandBehavior behavior)
at Microsoft.Data.Sqlite.SqliteCommand.ExecuteDbDataReader(CommandBehavior behavior)
at System.Data.Common.DbCommand.ExecuteReader()
at Microsoft.EntityFrameworkCore.Storage.RelationalCommand.ExecuteReader(RelationalCommandParameterObject parameterObject)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.InitializeReader(DbContext _, Boolean result)
at Microsoft.EntityFrameworkCore.Storage.NonRetryingExecutionStrategy.Execute[TState,TResult](TState state, Func`3 operation, Func`3 verifySucceeded)
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
public class DataContext : DbContext
{
// Für die zu erzeugende Tabelle nach dem Code first Prinzip
public DbSet<Person> Personen { get; set; }
public DbSet<Geschlecht> Geschlechter { get; set; }
public DbSet<Herkunft> Herkunft { get; set; }
public DbSet<Kontinent> Kontinent { get; set; }
public DbSet<Hobby> Hobby { get; set; }
public DbSet<PersonHobby> PersonHobby { get; set; }
public DbSet<VW_Test> VW_Test { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite(@"Data Source=D:\Daten\EntityFrameworkTutorial.db");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
var personBuilder = Build<Person>(modelBuilder);
var geschlechtBuilder = Build<Geschlecht>(modelBuilder);
var herkunftBuilder = Build<Herkunft>(modelBuilder);
var kontinentBuilder = Build<Kontinent>(modelBuilder);
var hobbyBuilder = Build<Hobby>(modelBuilder);
var personhobbyBuilder = Build<PersonHobby>(modelBuilder);
// Property Bedingungen festlegen
personBuilder
.Property(x => x.Geburtsdatum)
.IsRequired();
personBuilder
.Property(x => x.HerkunftId)
.IsRequired();
personBuilder
.Property(x => x.IQ)
.HasDefaultValue(0)
.IsRequired();
herkunftBuilder
.Property(x => x.Deutschsprachig)
.HasDefaultValue(false);
// 1 zu n Beziehungen
personBuilder
.HasOne(x => x.Geschlecht)
.WithMany(x => x.Personen)
.HasForeignKey(x => x.GeschlechtId);
personBuilder
.HasOne(x => x.Herkunft)
.WithMany(x => x.Personen)
.HasForeignKey(x => x.HerkunftId);
herkunftBuilder
.HasOne(x => x.Kontinent)
.WithMany(x => x.Herkunft)
.HasForeignKey(x => x.KontinentId);
// m zu n Beziehungen
personhobbyBuilder
.HasOne(x => x.Person)
.WithMany(x => x.PersonenHobbys)
.HasForeignKey(x => x.PersonId);
personhobbyBuilder
.HasOne(x => x.Hobby)
.WithMany(x => x.PersonenHobbys)
.HasForeignKey(x => x.HobbyId);
// View
modelBuilder.Entity<VW_Test>()
.HasNoKey()
.ToView("VW_Test");
base.OnModelCreating(modelBuilder);
}
private EntityTypeBuilder<T> Build<T>(ModelBuilder mb)
where T : Entity
{
var entity = mb.Entity<T>();
entity.HasKey(x => x.Id);
// Shadow Properties anlegen die für Entity nicht sichtbar sind und autom. gefüllt werden
entity.Property<string>("LatestUser")
.HasDefaultValue("Admin");
return entity;
}
}
Der Zugriff auf alle anderen Tabellen klappt problemlos.
Anbei noch ein Auszug aus meinem DB Browser, die Ansicht existiert und kann auch mit SQL abgerufen werden im DB Browser.
das Thema mit await und async wollte ich mir separat ansehen, habe erstmal darauf verzichtet da ich noch nicht wirklich verstehe was da passiert, bzw. was es genau bringt. Könntest du es evtl. kurz beschreiben anhand eines kleinen Beispiels, oder mir evtl. ein gutes Tutorial dazu emphelen?
Und kannst du mir auch noch erklären wozu genau das dient? brauch man das Ausrufungszeichen hinter dem null?
ich bekomme beim Zugriff auf ein View welches definitiv auf der Sqlite DB existiert den Fehler "no such table: VW_Test". Der generelle Zugriff auf die Tabellen funktioniert wunderbar. Könnt ihr mir evtl. sagen was hier das Problem ist?
ich bin gerade dabei mir EF Core anzueignen. Hier mein Beispiel mit Sqlite:
public class DataContext : DbContext
{
// Für die zu erzeugende Tabelle nach dem Code first Prinzip
public DbSet<Person> Personen { get; set; }
public DbSet<Geschlecht> Geschlechter { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlite(@"Data Source=D:\Daten\Steven IT\Daten\C# Entity Framework Core\Beispielanwendung Einfach\Beispielanwendung Einfach\Data\EntityFrameworkTutorial.db");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Geschlecht>()
.HasMany(g => g.Personen)
.WithOne(p => p.Geschlecht);
}
}
public class Person
{
public int Id { get; set; }
public string Vorname { get; set; }
public string Nachname { get; set; }
public Geschlecht Geschlecht { get; set; }
}
public class Geschlecht
{
public int Id { get; set; }
public string Bezeichnung { get; set; }
public List<Person> Personen { get; set; }
}
class Program
{
static void Main(string[] args)
{
using (var db = new DataContext())
{
var maennlich = new Geschlecht();
maennlich.Bezeichnung = "Männlich";
db.Geschlechter.Add(maennlich);
var weiblich = new Geschlecht();
weiblich.Bezeichnung = "Weiblich";
db.Geschlechter.Add(weiblich);
db.Personen.Add(person);
person = new Person();
person.Vorname = "Steven";
person.Nachname = "S.";
person.Geschlecht = maennlich;
db.Personen.Add(person);
person = new Person();
person.Vorname = "Lisa";
person.Nachname = "S.";
person.Geschlecht = weiblich;
db.Personen.Add(person);
db.SaveChanges();
}
using (var db = new DataContext())
{
foreach (var person in db.Personen)
{
Console.WriteLine($"{person.Id}. {person.Vorname} {person.Nachname} ({person.Geschlecht.Bezeichnung})");
}
}
Console.ReadKey();
}
}
Das speichern klappt wunderbar, hier wird die Id des Geschlechts autom. hinzugefügt.
Jedoch ist beim Anzeigen der Daten in der Console person.Geschlecht = null. In der Datenbank sieht alles gut aus.
Könnt ihr mir sagen was hier noch fehlt?
ich habe mir ein Statusfenster gebaut und möchte dieses ständig aktualisieren während der Laufzeit.
Das klappt zwar über INotifyPropertyChanged, jedoch immer nur wenn das Programm gerade nichts zu tun hat. In Win Forms konnte man einfach this.Refresh() machen, was mache ich hier falsch?
namespace PSWPF
{
public partial class WPFSplashScreen : Window
{
#region Props und Konstruktor
private Status oStatus;
public WPFSplashScreen(string sProgramName, string sVersion)
{
InitializeComponent();
labProgramName.Content = sProgramName;
labVersion.Content = sVersion;
oStatus = new Status();
this.DataContext = oStatus;
}
#endregion
#region Hilfsmethoden
public void SetStatusText(string sText)
{
oStatus.sStatus = sText;
}
public string GetStatusText()
{
return oStatus.sStatus;
}
#endregion
}
public class Status : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private string _status;
public string sStatus
{
get { return _status; }
set
{
_status = value.Trim();
OnPropertyChanged("sStatus");
}
}
private void OnPropertyChanged(string sProperty)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(sProperty));
}
}
}
Diesen öffne ich über meine Hauptanwendung und versuche ihn zur Laufzeit zu ändern.
...
this.oWPFSplashScreen = new WPFSplashScreen(this.ProgramName, this.Version);
this.oWPFSplashScreen.Show();
this.oWPFSplashScreen.SetStatusText("Login...");
...
Das Binding funktioniert soweit, jedoch sehe ich den Text "Login..." erst wenn alle Prozesse nach this.oWPFSplashScreen.SetStatusText("Login..."); abgeschlossen sind. Wie bekomme ich den Text noch während die Methode abgearbeitet wird angzeigt?
Da ich noch ziemlicher Anfänger bin würde ich mich über ein ausführliches Beispiel was ich zu tun habe sehr freuen.
ich habe in einem seperaten Projekt ein Window welches in den Ressourcen ein festes Bild hat. Pfad "Resources\Logo.bmp". Dieses habe ich über die Projekteigenschaften auch unter Ressourcen hinzugefügt.
In diesem Projekt zeige ich das Image so an:
Das funktioniert auch in dem Projekt. Wenn ich die dll jedoch in einem anderen Projekt einbinde und dieses Window öffnen will mit...
WPFWindow oWPFWindow = new WPFWindow();
oWPFWindow .Show();
..dann zeigt er mir das Fenster ohne das Logo an. Wie kann ich das Logo fest in diesem Window verankern, ohne das ich es im neuen Projekt auch wieder einbinden muss?
Nun versuche ich diese in einem neuen WPF Projekt einzubinden.
...
using PSBase.FE.WPF;
namespace Test
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : PSWPF
{
public MainWindow()
{
InitializeComponent();
}
}
}
Leider scheine ich zu blöd zu sein um das Ganze zu verstehen. Ich bräuchte evtl. etwas Starthilfe.
public class Repository
{
private string sSQLPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "Team.SQLite");
public Repository()
{
using (SQLiteConnection con = new SQLiteConnection(new SQLitePlatformAndroidN(), sSQLPathSpielstatistik, false))
{
con.CreateTable<SAI_Saison>();
con.CreateTable<SPI_Spieler>();
con.CreateTable<SAI_SPI_Saison_Spieler>();
}
}
private List<SPI_Spieler> GetAll_SPI_Spieler()
{
using (SQLiteConnection con = new SQLiteConnection(new SQLitePlatformAndroidN(), sSQLPath, false))
{
return con.Table<SPI_Spieler>().Where(s => s.Aktiv == true).ToList() ?? new List<SPI_Spieler>();
}
}
public List<SAI_Saison> GetAll_SAI_Saison()
{
using (SQLiteConnection con = new SQLiteConnection(new SQLitePlatformAndroidN(), sSQLPath, false))
{
return con.Table<SAI_Saison>().ToList() ?? new List<SAI_Saison>();
}
}
private SAI_SPI_Saison_Spieler Get_SAI_SPI_Saison_Spieler(int iSaison_ID, int iSpieler_ID)
{
using (SQLiteConnection con = new SQLiteConnection(new SQLitePlatformAndroidN(), sSQLPath, false))
{
return con.Table<SAI_SPI_Saison_Spieler>().Where(s => s.Saison_ID == iSaison_ID && s.Spieler_ID == iSpieler_ID).ToList().FirstOrDefault() ?? new SAI_SPI_Saison_Spieler();
}
}
}
Hier ein Auszug aus meiner Repository Klasse aus App1. Jetzt will ich im Grunde lediglich aus App2 auf die bereits dort gespeicherten Daten zugreifen.
Am besten arbeite ich immer mit Video Tutorials. Nur leider habe ich noch keines gefunden was mich weiter bringt.
ich habe zwei Apps mit ähnlicher Datenbankstruktur welche beide mit SQLLite erstellt wurden.
hier ein Beispiel.
// Zugriff aus der App 1
private string sSQLPath = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), "App.SQLite");
// Pfad: "/data/user/0/com.App/files/App.SQLite"
using (SQLiteConnection con = new SQLiteConnection(new SQLitePlatformAndroidN(), sSQLPath, false))
{
con.CreateTable<TAB_Tabelle>();
// Insert...
}
Jetzt Will ich aus der zweiten App auf die Datenbank der ersten App zugreifen um z.B. grundlegende Daten zu übernehmen.
// Zugriff aus der App 2
private string sSQLPath = "/data/user/0/com.App/files/App.SQLite"
if (File.Exists(sSQLPath))
{
using (SQLiteConnection con = new SQLiteConnection(new SQLitePlatformAndroidN(), sSQLPath, false))
{
con.CreateTable<TAB_Tabelle>();
// Get...
}
}
Hier kommt die Fehlermeldung SQLite.Net.SQLiteException: Could not open database file: /data/user/0/com.App/files/Trainingsbeteiligung.SQLite (CannotOpen).
Wenn ich z.B. die Datenbank kopieren will mit File.Copy("/data/user/0/com.App/files/App.SQLite", "/data/user/0/com.App2/files/App.SQLite", true);,
kommt die Fehlermeldung System.UnauthorizedAccessException: Access to the path.
Evtl. ist es ein Berechtigungsproblem.
Geht es überhaupt auf die DB der anderen App zu zu greifen?
Die WebMethode ist meine eigene. Leider hilft auch das löschen und neu erstellen der dlls nicht.
Komisch ist das ich aus einer anderen Konsolenanwendung in den WS debuggen kann. Es läuft alles lokal über einen WS der auch lokal ist. Die Konsolenanwendung ist doch im Grunde nichts anderes wie die Win Anwendung.
seit kurzen habe ich ein Problem damit aus ein Windows Anwendung in meinen lokalen WS zu debuggen, per Einzelschritt. Hier kommt die angehängte Fehlermeldung.
Bevor ich jetzt den kompletten Code poste, hoffe ich das jemand evtl. auf anhieb weiß woher diese Fehlermeldung kommt.
gibt es eine Möglichkeit im DatePicker mehrere Tage zu markieren, um zu erkennen ob zu bestimmten Tagen z.B. bereits Einträge hinterlegt sind? Quasi genauso wie der heutige Tag farbig anders dargestellt ist.
Versuche ich, seltsamerweise steht in Extras -> Optionen -> Umgebung -> Internationale Einstellung nur Deutsch zur Auswahl. Will ich Englisch installieren sagt er mir es wäre bereits installiert.
Er fängt auch an im Release Verzeichnis ein entsprechendes Unterverzeichnis ...apk.mSYM zu erstellen, leider kommt jedoch die folgende Fehlermeldung:
Fehler
Es wurden Konflikte zwischen verschiedenen Versionen derselben abhängigen Assembly gefunden, die nicht gelöst werden können.
Diese Verweiskonflikte werden im Buildprotokoll aufgelistet, wenn die Protokollausführlichkeit auf "Ausführlich" festgelegt ist.
Ich weiß leider nicht wirklich wo genau ich jetzt suchen soll.
zu ersetzen, jedoch kommt nun die unten stehende Fehlermeldung.
Fehlt mir noch ein bestimmtes Paket? Die dll SQLite.Net zeigt die version 3.1.0 obwohlich das Paket SQLite.Net PCL Version 3.1.1 installiert habe.
Ich habe folgendes gefunden wenn ich nur die Warnungen aktiviere. Hier finde ich ebenfalls auch die Meldung um die es geht. Hilft das zur weiteren Analyse?