Benutzer mit den meisten Antworten
Datenmodell -- Allgemein gehalten, LinQ einer 1:n m:n Verbindungen

Frage
-
Hallo,ich würde gerne eine Allgemeinlösung bekommen.
Ich habe ein Dataset mit Datatables m:n und 1:n Relations.Jetzt will ich in Abhängigkeit von der Position und dem Variablennamen
eine Abfrage erzeugen, um in der Tabelle den Inhalt zu bekommen.Wie müßte ich das machen.
Primär-/FremdschlüsselLinqpad
Mit Linqpad kann ich keine XML Datei laden.Die Daten halten sich so in Grenzen, dass eine Datenbank unsinnig wäre.Gibt es Möglichkeiten über so einen Art Wizard die XML Datei zu laden und dann so eine Art SQL Query zu erzeugen.Oder über die XSD Datei?
Grüße Oliver
var qryPass3 = (from a in A.AsEnumerable()
join b in B.AsEnumerable() on a.Id equals b.IdSideNumber from c in C.AsEnumerable() join d in D.AsEnumerable() on decimal. where (b.Active == false) select new { Element11 = a.Field<Int32>("Spaltenname A"), Element12 = b.Field<Int32>("Spaltenname A"), Element13 = b.Field<Int32>("Spaltenname B"), Element14 = b.Field<bool>("Active"), }).ToList();
- Bearbeitet Oliver Müller12 Mittwoch, 15. November 2017 17:30
Antworten
-
Hi Oliver,
hier mal eine Konsolendemo, wie man die Aufgabe lösen kann:using System; using System.Collections.Generic; using System.Linq; namespace ConsoleApp1 { class Program26 { static void Main(string[] args) { try { Demo c = new Demo(); c.Execute(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } Console.WriteLine("Fertig, Abschluss mit beliebiger Taste"); Console.ReadKey(); } internal class Demo { internal void Execute() { // Demo-Daten generieren List<cDTA> DTA = new List<cDTA>(); List<cDTB> DTB = new List<cDTB>(); List<cDTC> DTC = new List<cDTC>(); List<cDTD> DTD = new List<cDTD>(); List<cDTBC> DTBC = new List<cDTBC>(); for (int i = 1; i < 10; i++) { DTA.Add(new cDTA() { Id = i, Name = $"DTA {i}" }); DTC.Add(new cDTC() { Id = i, Name = $"DTC {i}" }); for (int k = 1; k < 10; k++) { DTB.Add(new cDTB() { Id = i, Name = $"DTB {i} {k}", Position = k, id_A = i }); DTD.Add(new cDTD() { Id = i, Name = $"DTD {i} {k}", Inhalt = $"Inhalt {k}", id_C = i }); for (int l = 1; l < 10; l++) { DTBC.Add(new cDTBC() { Id = i, Name = $"DTBC {i} {k} {l}", id_B = k, id_C = i }); } } } // var q = from b in DTB where b.Position == 5 // in DTB nur Daten mit bestimmer Position join bc1 in DTBC on b.Id equals bc1.id_B into bcg // Liste der Childs zu Master mit Position=5 from bc2 in bcg join c in DTC on bc2.id_C equals c.Id into c2 // Liste der verknüpften DTC's from c1 in c2 join d in DTD on c1.Id equals d.id_C // Verknüpfung zum Child DTD where d.Name == "DTD 1 3" // dort nach Namen selektieren select new { b = b.Name, bc2 = bc2.Name, c1 = c1.Name, inhalt = d.Inhalt }; // neues anonymes Ergebnis-Objekt foreach (var o in q) { Console.WriteLine($"{o.b} - {o.bc2} - {o.c1} - {o.inhalt}"); } } /// <summary> /// Master von cDTB /// </summary> class cDTA { public int Id { get; set; } public string Name { get; set; } } /// <summary> /// Child von cDTA und Master zu cDTBC, d.h. n:m zu cDTC /// </summary> class cDTB { public int Id { get; set; } public string Name { get; set; } public int Position { get; set; } public int id_A { get; set; } } /// <summary> /// n:m zwischen cDTB und cDTC /// </summary> class cDTBC { public int Id { get; set; } public string Name { get; set; } public int id_B { get; set; } public int id_C { get; set; } } /// <summary> /// Master von cDTD und Master zu cDTBC, d.h. n:m zu cDTB /// </summary> class cDTC { public int Id { get; set; } public string Name { get; set; } } /// <summary> /// Child von cDTC /// </summary> class cDTD { public int Id { get; set; } public string Name { get; set; } public string Inhalt { get; set; } public int id_C { get; set; } } } } }
--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks- Als Antwort vorgeschlagen Peter Fleischer Sonntag, 19. November 2017 21:03
- Als Antwort markiert Oliver Müller12 Montag, 20. November 2017 11:42
-
Hi Oliver,
die IntelliSense zeigt an der Stelle, wo jetzt into steht, nur 3 Möglichkeiten. Da hält sich der Aufwand, mal zu lesen, in Grenzen. Das Schöne an LinQ ist, dass man die Teilabfragen auch hintereinander separat ausführen kann und damit schrittweise die Lösung erstellen:var q1 = from b in DTB where b.Position == 5 // in DTB nur Daten mit bestimmer Position join bc1 in DTBC on b.Id equals bc1.id_B select bc1 // Liste der Childs zu Master mit Position=5 var q2 = from bc2 in q1 join c in DTC on bc2.id_C equals c.Id select c // Liste der verknüpften DTC's .. usw.
--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks- Bearbeitet Peter Fleischer Montag, 20. November 2017 12:04
- Als Antwort markiert Oliver Müller12 Montag, 20. November 2017 18:28
Alle Antworten
-
Hallo Oliver,
Wie ich Deinem Bild und Code entnehme, erfolgt die innere Verknüpfung zwischen A und B durch die Entsprechung von A.Id und B.IdSideNumber, aber wie wird die Verknüpfung zwischen C und D vollzogen? Da die vierte Zeile in Deinem Code unvollständig aussieht, würdest Du klarlegen, welche Datasetfelder in C und D bei der Verknüpfung entsprechen sollen und ob sie auch Datasetfeldern in A und/oder B gleich sein sollen?
Gruß,
DimitarBitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „IT-Pros helfen IT-Pros“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.
-
Hallo Dimitar,
also, ich habe eine 1:n Verknüpfung Tabelle A zu B
ich habe eine 1:n Verknüpfung Tabelle C zu D
ich habe ein Mapping für die Tabelle BC mit Fremdschlüssel von A mit Fremdschlüssel von C
C kann viele Elemente von D haben.
D hat den Fremdschlüssel von C
C (Id) D (IdFremdschlüssel_Von_C)
D hat 'Variablenname', 'Inhalt' als Spaltennamen.
Jetzt gibt der User die Position aus B vor, mit dem gewünschten Variablennamen von D. Dann soll einfach der Inhalt zugeliefert werden. Da ist die Frage, wie kann ich das erreichen, wie sieht die LinQ Abfrage aus, was muss ich beachten, durch die m:n Verknüpfung zwischen B und C ist es schwierig. Danke für Tipps.
Grüße Oliver
- Bearbeitet Oliver Müller12 Donnerstag, 16. November 2017 17:56
-
Hi Oliver,
ich habe den Thread mehrfach gelesen und verstehe trotzdem nicht Dein Datenmodell. Kannst Du nicht mal einfach nur die Tabellennamen mit den Feldnamen aufführen und die Beziehungen zwischen ihnen, z.B. so:TabA
int ID - Primärschlüssel
TabB
int ID - Primärschlüssel
int FK - Fremdschlüssel zu TabA.ID
int Position - Feld, nach dem zu filtern ist--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks -
Hallo,anbei nun das korrekte Datenbankmodell.
//TabA // int ID -Primärschlüssel //TabB // int ID -Primärschlüssel // int FK -Fremdschlüssel zu TabA.ID // int Position -Feld, nach dem zu filtern ist //TabC // int ID -Primärschlüssel // int FK -Fremdschlüssel zu TabD.ID // int Index -Feld, nach dem zu filtern ist //TabD // int ID -Primärschlüssel // int FK -Fremdschlüssel zu TabC.ID // string VariableName-Feld, nach dem zu filtern ist // string Inhalt-Feld, das ausgegeben werden muss //Die Positionen können viele Indexe aufweisen //Die Indexe können aber auch zu unterschiedlichen Positionen gehören // Pos...Index //1 1 //1 2 //1 3 //2 4 //3 4 //3 1
Viele Grüße Oliver -
Hi Oliver,
dieses Modell hat aber nichts mit n:m zu tun. Da ist überall eine 1:n Master-Child-Beziehung:TabA
TabB
TabD
TabC--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks -
Hallo Peter,
//TabA // int ID -Primärschlüssel //TabB // int ID -Primärschlüssel // int FK -Fremdschlüssel zu TabA.ID // int Position -Feld, nach dem zu filtern ist //TabC // int ID -Primärschlüssel // int FK -Fremdschlüssel zu TabD.ID // int Index -Feld, nach dem zu filtern ist //TabD // int ID -Primärschlüssel // int FK -Fremdschlüssel zu TabC.ID // string VariableName-Feld, nach dem zu filtern ist // string Inhalt-Feld, das ausgegeben werden muss //Die Positionen können viele Indexe aufweisen //Die Indexe können aber auch zu unterschiedlichen Positionen gehören // Tab BC also // int ID -Primärschlüssel // int ID_FK -Fremdschlüssel zu TabB.ID // int ID_FK -Fremdschlüssel zu TabC.ID // Pos...Index //1 1 //1 2 //1 3 //2 4 //3 4 //3 1
Ups. Vergessen.
Grüße Oliver
- Bearbeitet Oliver Müller12 Freitag, 17. November 2017 18:01
-
Hi Oliver,
jetzt hast Du eine n:m Beziehung zwischen TabB und TabC. TabA ist Master zu TabB, TabD ist Master zu TabC.Die einzige Frage, die ich im Thread gefunden habe, war: Oder über die XSD Datei?
Was erwartest Du für eine Antwort?
Natürlich kann man dafür eine Schema-Datei (xsd) erstellen. Viel wichtiger ist: "Was willst Du erreichen?". Wie sieht die Aufgabenstellung aus?
--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks -
Hallo Peter,
>jetzt hast Du eine n:m Beziehung zwischen TabB und TabC.
Ja!
>TabA ist Master zu TabB,
ja!
TabD ist Master zu TabC.
Nein!
So TabC ist Master zu TabD
>Jetzt gibt der User die Position aus B vor, mit dem gewünschten Variablennamen von D. Dann soll
>einfach der Inhalt zugeliefert werden. Da ist die Frage, wie kann ich das erreichen, wie sieht die
>LinQ Abfrage aus, was muss ich beachten, durch die m:n Verknüpfung zwischen B und C ist es schwierig.
- D hat 'Variablenname', 'Inhalt' als Spaltennamen.
Danke für Tipps.
Viele Grüße Oliver
-
Hi Oliver,
da nach Deiner Beschreibung zeigt der Fremdschlüssel in TabC auf den Primärschlüssel von TabD.//TabC
// int ID -Primärschlüssel
// int FK -Fremdschlüssel zu TabD.ID
// int Index -Feld, nach dem zu filtern ist
//TabDDamit Ist TabD Master.
--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks -
Jetzt stimmt's aber😉
//TabA
// int ID -Primärschlüssel
//TabB
// int ID -Primärschlüssel
// int FK -Fremdschlüssel zu TabA.ID
// int Position -Feld, nach dem zu filtern ist
//TabC
// int ID -Primärschlüssel
// int Index -Feld, nach dem zu filtern ist
//TabD
// int ID -Primärschlüssel
// int FK -Fremdschlüssel zu TabC.ID
// string VariableName-Feld, nach dem zu filtern ist
// string Inhalt-Feld, das ausgegeben werden muss
//Die Positionen können viele Indexe aufweisen
//Die Indexe können aber auch zu unterschiedlichen
Positionen gehören
// Tab BC also
// int ID -Primärschlüssel
// int ID_FK -Fremdschlüssel zu TabB.ID
// int ID_FK -Fremdschlüssel zu TabC.ID
// Pos...Index
//1 1
//1 2
//1 3
//2 4
//3 4
//3 1
Grüße Oliver
-
Hi Oliver,
Bau erst einmal ein passendes Datenmodell und formuliere bitte dann Deine Fragen etwas detaillierter.--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks -
Bau erst einmal ein passendes Datenmodell und formuliere bitte dann Deine Fragen etwas detaillierter.
Hallo Peter,ja auch hier hast wieder Recht, sauber aufzeichnen.Das Problem ist ja nicht das Befüllen. Da habe ich meine Id und ich kann diese als Fremdschlüssel der Child Tabelle zuweisen.Das Problem istTabelleA Name = Seite 1TabelleB Position = 5Befülle hier aus TabelleC Name 4,7,8TabelleC hat ja 4,7,8 drin mit Child Tabelle DName = HezZaehler Inhalt 0xAName = DezZaehler Inhalt 0035235Name = JulianDatum Inhalt 2342017Ich möchte a)bestehende Positionen befüllen, ändern.b) Ich möchte eine Query erstellenGib mir von Position 5, die Inhalte aus mit dem Name JulianDatum.Wie kann ich das korrekt umsetzen?Noch einen schönen Sonntag und Danke für Tipps.Viele Grüße OliverDataSetMzuN DSMzuN; DSMzuN = new DataSetMzuN(); DataRow[] arrRows; foreach (DataRelation relation in DSMzuN.DTA.ChildRelations) { if (relation.RelationName == "FK_DTA_DTB") { foreach (DataRow row in DSMzuN.DTB.Rows) { arrRows = row.GetChildRows(relation); // DataRowVersion.Proposed); // Print values of rows. foreach (var item in arrRows) {
- Bearbeitet Oliver Müller12 Sonntag, 19. November 2017 12:11
-
Hi Oliver,
hier mal eine Konsolendemo, wie man die Aufgabe lösen kann:using System; using System.Collections.Generic; using System.Linq; namespace ConsoleApp1 { class Program26 { static void Main(string[] args) { try { Demo c = new Demo(); c.Execute(); } catch (Exception ex) { Console.WriteLine(ex.ToString()); } Console.WriteLine("Fertig, Abschluss mit beliebiger Taste"); Console.ReadKey(); } internal class Demo { internal void Execute() { // Demo-Daten generieren List<cDTA> DTA = new List<cDTA>(); List<cDTB> DTB = new List<cDTB>(); List<cDTC> DTC = new List<cDTC>(); List<cDTD> DTD = new List<cDTD>(); List<cDTBC> DTBC = new List<cDTBC>(); for (int i = 1; i < 10; i++) { DTA.Add(new cDTA() { Id = i, Name = $"DTA {i}" }); DTC.Add(new cDTC() { Id = i, Name = $"DTC {i}" }); for (int k = 1; k < 10; k++) { DTB.Add(new cDTB() { Id = i, Name = $"DTB {i} {k}", Position = k, id_A = i }); DTD.Add(new cDTD() { Id = i, Name = $"DTD {i} {k}", Inhalt = $"Inhalt {k}", id_C = i }); for (int l = 1; l < 10; l++) { DTBC.Add(new cDTBC() { Id = i, Name = $"DTBC {i} {k} {l}", id_B = k, id_C = i }); } } } // var q = from b in DTB where b.Position == 5 // in DTB nur Daten mit bestimmer Position join bc1 in DTBC on b.Id equals bc1.id_B into bcg // Liste der Childs zu Master mit Position=5 from bc2 in bcg join c in DTC on bc2.id_C equals c.Id into c2 // Liste der verknüpften DTC's from c1 in c2 join d in DTD on c1.Id equals d.id_C // Verknüpfung zum Child DTD where d.Name == "DTD 1 3" // dort nach Namen selektieren select new { b = b.Name, bc2 = bc2.Name, c1 = c1.Name, inhalt = d.Inhalt }; // neues anonymes Ergebnis-Objekt foreach (var o in q) { Console.WriteLine($"{o.b} - {o.bc2} - {o.c1} - {o.inhalt}"); } } /// <summary> /// Master von cDTB /// </summary> class cDTA { public int Id { get; set; } public string Name { get; set; } } /// <summary> /// Child von cDTA und Master zu cDTBC, d.h. n:m zu cDTC /// </summary> class cDTB { public int Id { get; set; } public string Name { get; set; } public int Position { get; set; } public int id_A { get; set; } } /// <summary> /// n:m zwischen cDTB und cDTC /// </summary> class cDTBC { public int Id { get; set; } public string Name { get; set; } public int id_B { get; set; } public int id_C { get; set; } } /// <summary> /// Master von cDTD und Master zu cDTBC, d.h. n:m zu cDTB /// </summary> class cDTC { public int Id { get; set; } public string Name { get; set; } } /// <summary> /// Child von cDTC /// </summary> class cDTD { public int Id { get; set; } public string Name { get; set; } public string Inhalt { get; set; } public int id_C { get; set; } } } } }
--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks- Als Antwort vorgeschlagen Peter Fleischer Sonntag, 19. November 2017 21:03
- Als Antwort markiert Oliver Müller12 Montag, 20. November 2017 11:42
-
Hi Oliver,
wenn Dir das into fehlte, warum bemühst Du da nicht mal die Hilfe?--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks -
Hi Oliver,
die IntelliSense zeigt an der Stelle, wo jetzt into steht, nur 3 Möglichkeiten. Da hält sich der Aufwand, mal zu lesen, in Grenzen. Das Schöne an LinQ ist, dass man die Teilabfragen auch hintereinander separat ausführen kann und damit schrittweise die Lösung erstellen:var q1 = from b in DTB where b.Position == 5 // in DTB nur Daten mit bestimmer Position join bc1 in DTBC on b.Id equals bc1.id_B select bc1 // Liste der Childs zu Master mit Position=5 var q2 = from bc2 in q1 join c in DTC on bc2.id_C equals c.Id select c // Liste der verknüpften DTC's .. usw.
--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks- Bearbeitet Peter Fleischer Montag, 20. November 2017 12:04
- Als Antwort markiert Oliver Müller12 Montag, 20. November 2017 18:28