Laden...

C# EF Core SQLite, lesen schreiben via primary / foreign key

Erstellt von jok3r89 vor 5 Jahren Letzter Beitrag vor 5 Jahren 1.813 Views
J
jok3r89 Themenstarter:in
70 Beiträge seit 2017
vor 5 Jahren
C# EF Core SQLite, lesen schreiben via primary / foreign key

verwendetes Datenbanksystem: SQLite

Hallo, ich mache gerade meine ersten versuche mit SQLite und EFCore in C#.

Ich habe ein kleines Tool geschrieben, mit dem 3 Tabellen gefüllt werden.

Die Datenbank ->


    public class DBContext : DbContext
    {
        public DbSet<PLCTyp> PLCSets { get; set; }
        public DbSet<DBTyp> DbSets { get; set; }
        public DbSet<VarTyp> VarSets { get; set; }

        private static bool _created = false;

        public DBContext()
        {
            if (!_created)
            {
                _created = true;
                //       Database.EnsureDeleted();
                Database.EnsureCreated();
            }
        }

        public void ClearDatabase()
        {
            Database.EnsureDeleted();
            Database.EnsureCreated();

        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlite("Data Source=MyDatabase.sqlite");
        }

public class PLCTyp
    {
        public int id { get; set; }
        public string name { get; set; }
        public string ip { get; set; }
        public string target { get; set; }
        public int cycle { get; set; }
    }

    public class DBTyp
    {
        public int id { get; set; }
        public List<PLCTyp> plcId { get; set; }
        public string name { get; set; }
        public int adress { get; set; }
        public int offset { get; set; }
        public int lengh { get; set; }
    }

    public class VarTyp
    {
        public int id { get; set; }
        public List<DBTyp> dbId { get; set; }
        public string name { get; set; }
        public int offset { get; set; }
        public int lengh { get; set; }
        public int varId { get; set; }
    }

Hier eine Abfrage



 List<DBTyp> getDBbyPlc(PLCTyp plc)
        {
            try
            {
                using (var db = _db)
                {
					var dbs = db.DbSets
						 .Where(b => b.plcId.Contains(plc)).
						 ToList();
						
                }
            }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

            return null;
        }

Ist das so richtig? Ich hab zu primary/ foreign key relativ wenig gefunden.

Zur Erklärung in der
Tabelle 1 befinden sich die Verbindungen "PLCTyp"
Tabelle 2 befinden sich die Streams "DBTyp" (hat nichts mit der Datenbank zu tun das heißt nur so)
Tabelle 3 sind die Datentypen die mit gemappt werden damit ich von dem Stream zu brauchbare Variablen komme "VarTyp".

Der Tag war lange und ich glaube ich hab einen großen Denkfehler vor mir....

Schon mal vielen Dank
Gruß

16.835 Beiträge seit 2008
vor 5 Jahren
  1. Nenn Dein DB Context richtig. DBContext : DbContext erkennt ja keiner den Unterschied und führt nur zu Verwirrung.
    Wenn Dein Tool PlcTool heisst, dann nenn den Context eben PlcToolDbContext - so ist es gedacht.
    Namen von Variablen und Klassen sollen immer Aussagen, was sie wirklich sind. =)

  2. Halte Dich an die Naming Guidelines von C#
    [Artikel] C#: Richtlinien für die Namensvergabe

  3. Deine Abfrage mit dem Ensure macht wenig Sinn.
    Ensure erstellt die Datenbank ohnehin nur, wenn sie nicht existiert.
    Ergo brauchst Du die Abfrage überhaupt nicht.

  4. Die Exception zu fangen und dann in Exception nur die Message zu legen führt dazu, dass Dir der gesamte StackTrace verloren geht.
    Hier an der Stelle die Exception überhaupt nicht fangen - macht kein Sinn

  5. ToList sollte man nur zurück geben, wenn man auch wirklich alle Inhalte dazu laden will.
    ToList führt immer den Query aus (Query Materializing) - sollte also gerade bei großen Resultaten vermieden werden

  6. Schau Dir den Repository Pattern an und dazu wie die Verbindung in einem Repository gehalten wird.
    Dein Code ist so nicht testbar (und es macht wenig sinn, dass in jeder Get-Abfrage die Verbindung aufgebaut wird; macht es unnötig langsam)

  7. Relations würde ich immer mit Hilfe der FluentAPI umsetzen; das hilft sehr schnell um potentielle Denkfehler zu finden. 👍

Ansonsten sehe ich keine Frage; und der Code ist ja sehr ähnlich zum offiziellen EF Core Beispiel.
Ob das funktioniert kannst Du ja selbst ausprobieren 😉

J
jok3r89 Themenstarter:in
70 Beiträge seit 2017
vor 5 Jahren

Naja bitte nicht gleich so streng, Ich versuche mich ein wenig einzuarbeiten und kopiere einiges zusamen um mal was zu testen.
Ich werde mich bemühen!


   protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
			modelBuilder.Entity<DBTyp>()
				 .HasOne(p => p.PLCTyp)
				 .WithMany(b => b.DbSets)
				 .HasForeignKey(p => p.PLCTypId);

			modelBuilder.Entity<VarTyp>()
				.HasOne(p => p.DBTyp)
				.WithMany(b => b.VarSets)
				.HasForeignKey(p => p.DBTypId);
		}
      
    }

    public class PLCTyp
    {
        public int PLCTypId { get; set; }
        public string name { get; set; }
        public string ip { get; set; }
        public string target { get; set; }
        public int cycle { get; set; }

		public List<DBTyp> DbSets { get; set; }
	}

    public class DBTyp
    {
        public int DBTypId { get; set; }
        public string name { get; set; }
        public int adress { get; set; }
        public int offset { get; set; }
        public int lengh { get; set; }

		public int PLCTypId { get; set; }
		public PLCTyp PLCTyp { get; set; }

		public List<VarTyp> VarSets { get; set; }
	}


public void InsertDB( PLCTyp pLCTyp, DBTyp dBTyp)
        {
            try
            {
                using (var db = new DBContext())
                {
					var  plc = db.PlcSets.Where(p => p.PLCTypId == pLCTyp.PLCTypId).Single();
					plc.DbSets.Add(dBTyp);
					
                    db.SaveChanges();
                }
            }
            catch (Exception ex)
            {
				Console.WriteLine(ex.Message);
			}
		}

aktuell hänge ich hier, ich würde gerne in PLCSets einen Eintrag updaten aber irgendwie bekomme ich das nicht zu stande
Mir fällt ständig ein null ref Exception.
In den EF Core Beispielen wird das auch mit dem inlucde gemacht. Das fehlt bei mir komplett.
Weiß wer rat?

P
441 Beiträge seit 2014
vor 5 Jahren

Wenn du die Navigation Property als virtual deklarierst kann EF das nachladen für dich übernehmen:
http://www.entityframeworktutorial.net/lazyloading-in-entity-framework.aspx

16.835 Beiträge seit 2008
vor 5 Jahren

Schau Dir auch bitte den Repository Pattern an.
Man sollte es tunlichst vermeiden, in einer ausführenden DB-Methode (hier Insert und Get) jedes mal die Datenbankverbindung neu zu erstellen; macht wenig bis keinen Sinn.

Zudem ist

          }
            catch (Exception ex)
            {
                throw new Exception(ex.Message);
            }

            return null;

kein valides Exception Handling.
Das unterdrückt alles, was man nicht unterdrücken sollte. ⚠

Es gibt hier keine Notwendigkeit im DB-Layer eine Exception zu fangen - und verfälscht sogar den StackTrace. 😉