ich habe zwei Tabellen, die eine n:m Beziehung zueinander haben, welche über eine Hilfstabelle realisiert ist.
Ich benutze unter Silverlight 4 das Entity Framework. Dort sind diese Assoziationen als Navigation Property geführt.
Ich hätte nun gerne, dass mur zu jedem Datensatz von Tabelle A alle zugehörigen Datensätze von Tabelle B in einem extra Grid (da ja auch andere Spaltennamen) angezeigt werden.
Ich stelle mir das so vor, dass ich jeden Eintrag Gruppieren kann (ungefähr wie beim PagedCollectionView).
Mir fehlt jedoch absolut der Ansatz dafür. Kann mir jemand weiterhelfen?
Ja klar, da gibts im Xaml eine Attached Property die heißt RowDetails und dort kannst du ein DataTemplate festlegen.
Vielen Dank für deine Antwort. Das scheint auch zu funktionieren.
Ich habe TabelleA und TabelleB als Entitäten importiert. Die Assoziationen kann ich über NavigationPropertys erreichen.
Den Inhalt meines "Haupt-"DataGrids hole ich mir über IQueryable<TableA>. Auf was muss ich das Binding nun im Unter-DataGrid setzen?
TableA sollte dann doch ein Navigation Property zu TableB haben. Diese Collection kannst du doch dann verwenden, sowas wie TableA.TableBList.
Die Get-Query liefert mir aber ein EntitySet bzw. IQueryable<TableA> zurück. Diese enthält folglich alle Sätze.
Was ich bräuchte wäre aber immer alle TableB-Datensätze bezogen auf 1nen TableA-Datensatz.
Ein ORM stellt keine Tabellen sondern Objektgraphen dar. Wenn du beispielsweise sowas wie
C# Code:
var qry = ctx.TableASet.Include("TableBSet");
C# Code:
var qry = ctx.TableASet.Include("TableBSet");
C# Code:
var qry = ctx.TableASet.Include("TableBSet");
machst, solltest eine Aufzählung von A's haben an denen über das Navigationsproperty für jedes A die entsprechenden B's dranhängen. Also A.BList oder wie immer das NavProperty heisst sollte dir die B's geben die mit diesem konkreten A verknüpft sind. Der Binding-path der ItemsSource könnte dann "A.BList" heißen.
Wenn die verknüpfende DB-Tabelle zwischen A und B noch weitere Attribute als die Fremdschlüssel besitzt dann mußt du diese miteinbeziehen
C# Code:
var qry = ctx.TableASet.Include("TableABMapper.TableBSet");
C# Code:
var qry = ctx.TableASet.Include("TableABMapper.TableBSet");
C# Code:
var qry = ctx.TableASet.Include("TableABMapper.TableBSet");
und dann entsprechend "A.ABMapper" als Path.
Sonst müßtest du mal konkret zeigen was du da machst.
Ich versuch es mal mit anderen Worten auszudrücken.
Ich habe folgende SQL-Tabellen:
TableA:
Code:
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
CREATE TABLE [dbo].[TableA](
[aID] [int] IDENTITY(1,1) NOT NULL,
[aName] [varchar](32) NOT NULL,
CONSTRAINT [PK_aID] PRIMARY KEY CLUSTERED
(
[aID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Code:
1 2 3 4 5 6 7 8
CREATE TABLE [dbo].[TableA](
[aID] [int] IDENTITY(1,1) NOT NULL,
[aName] [varchar](32) NOT NULL,
CONSTRAINT [PK_aID] PRIMARY KEY CLUSTERED
(
[aID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Code:
1 2 3 4 5 6 7 8
CREATE TABLE [dbo].[TableA](
[aID] [int] IDENTITY(1,1) NOT NULL,
[aName] [varchar](32) NOT NULL,
CONSTRAINT [PK_aID] PRIMARY KEY CLUSTERED
(
[aID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
TableB:
Code:
1 2 3 4 5 6 7 8
1 2 3 4 5 6 7 8
CREATE TABLE [dbo].[TableB](
[bID] [int] IDENTITY(1,1) NOT NULL,
[bName] [varchar](32) NOT NULL,
CONSTRAINT [PK_bID] PRIMARY KEY CLUSTERED
(
[bID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Code:
1 2 3 4 5 6 7 8
CREATE TABLE [dbo].[TableB](
[bID] [int] IDENTITY(1,1) NOT NULL,
[bName] [varchar](32) NOT NULL,
CONSTRAINT [PK_bID] PRIMARY KEY CLUSTERED
(
[bID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Code:
1 2 3 4 5 6 7 8
CREATE TABLE [dbo].[TableB](
[bID] [int] IDENTITY(1,1) NOT NULL,
[bName] [varchar](32) NOT NULL,
CONSTRAINT [PK_bID] PRIMARY KEY CLUSTERED
(
[bID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
TableA_B:
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
CREATE TABLE [dbo].[TableA_TableB](
[aID] [int] NOT NULL,
[bID] [int] NOT NULL,
CONSTRAINT [PK_Group_Module] PRIMARY KEY CLUSTERED
(
[aID]] ASC,
[bID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[TableA_TableB] WITH CHECK ADD CONSTRAINT [FK_TableA_TableB_TableA] FOREIGN KEY([aID])])
REFERENCES [dbo].[Group] ([aID])
ALTER TABLE [dbo].[TableA_TableB] WITH CHECK ADD CONSTRAINT [FK_TableA_TableB_TableB] FOREIGN KEY([bID])
REFERENCES [dbo].[Module] ([bID])
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
CREATE TABLE [dbo].[TableA_TableB](
[aID] [int] NOT NULL,
[bID] [int] NOT NULL,
CONSTRAINT [PK_Group_Module] PRIMARY KEY CLUSTERED
(
[aID]] ASC,
[bID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[TableA_TableB] WITH CHECK ADD CONSTRAINT [FK_TableA_TableB_TableA] FOREIGN KEY([aID])])
REFERENCES [dbo].[Group] ([aID])
ALTER TABLE [dbo].[TableA_TableB] WITH CHECK ADD CONSTRAINT [FK_TableA_TableB_TableB] FOREIGN KEY([bID])
REFERENCES [dbo].[Module] ([bID])
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
CREATE TABLE [dbo].[TableA_TableB](
[aID] [int] NOT NULL,
[bID] [int] NOT NULL,
CONSTRAINT [PK_Group_Module] PRIMARY KEY CLUSTERED
(
[aID]] ASC,
[bID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[TableA_TableB] WITH CHECK ADD CONSTRAINT [FK_TableA_TableB_TableA] FOREIGN KEY([aID])])
REFERENCES [dbo].[Group] ([aID])
ALTER TABLE [dbo].[TableA_TableB] WITH CHECK ADD CONSTRAINT [FK_TableA_TableB_TableB] FOREIGN KEY([bID])
REFERENCES [dbo].[Module] ([bID])
Diese möchte ich quasi folgendermaßen in meinem Grid anzeigen:
Code:
SELECT a.[aID]
,a.[aName]
,b.[bID]
,b.[bName]
FROM [Database0].[dbo].[TableA] as a
LEFT JOIN [Database0].[dbo].[TableA_TableB] as ab ON a.[aID] = ab.[aID]
LEFT JOIN [Database0].[dbo].[TableB] as b ON ab.[bID] = m.[bID]
Code:
SELECT a.[aID]
,a.[aName]
,b.[bID]
,b.[bName]
FROM [Database0].[dbo].[TableA] as a
LEFT JOIN [Database0].[dbo].[TableA_TableB] as ab ON a.[aID] = ab.[aID]
LEFT JOIN [Database0].[dbo].[TableB] as b ON ab.[bID] = m.[bID]
Code:
SELECT a.[aID]
,a.[aName]
,b.[bID]
,b.[bName]
FROM [Database0].[dbo].[TableA] as a
LEFT JOIN [Database0].[dbo].[TableA_TableB] as ab ON a.[aID] = ab.[aID]
LEFT JOIN [Database0].[dbo].[TableB] as b ON ab.[bID] = m.[bID]
D.h. generell möchte ich jedes Vorkommen von TabelleA auch anzeigen, selbst wenn keine TabelleB in TabelleA_TabelleB dazu vorhanden ist.
Ist eine TabelleB vorhanden, möchte ich alle Vorkommen von TabellB im Eintrag unter dem Eintrag zu TabelleA in einem separierten DataGrid anzeigen.
Es wäre wirklich super, wenn mir jemand den letzten entscheidenden Hinweis geben könnte ;-)
PS:
Der XAML-Code dazu sieht momentan wie folgt aus:
private void tableADomainDataSource_LoadedData(object sender, System.Windows.Controls.LoadedDataEventArgs e)
{
var first = e.Entities.First() as BusinessApplication1.Web.Models.tableA;
var query = from tableB in first.TableBs select tableB;
System.Windows.MessageBox.Show(first.Name);
System.Windows.MessageBox.Show(query.Count().ToString());
foreach (BusinessApplication1.Web.Models.TableB tableB in query)
{
System.Windows.MessageBox.Show(tableB.Name);
}
if (e.HasError)
{
System.Windows.MessageBox.Show(e.Error.ToString(), "Load Error", System.Windows.MessageBoxButton.OK);
e.MarkErrorAsHandled();
}
}
C# Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
private void tableADomainDataSource_LoadedData(object sender, System.Windows.Controls.LoadedDataEventArgs e)
{
var first = e.Entities.First() as BusinessApplication1.Web.Models.tableA;
var query = from tableB in first.TableBs select tableB;
System.Windows.MessageBox.Show(first.Name);
System.Windows.MessageBox.Show(query.Count().ToString());
foreach (BusinessApplication1.Web.Models.TableB tableB in query)
{
System.Windows.MessageBox.Show(tableB.Name);
}
if (e.HasError)
{
System.Windows.MessageBox.Show(e.Error.ToString(), "Load Error", System.Windows.MessageBoxButton.OK);
e.MarkErrorAsHandled();
}
}
C# Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
private void tableADomainDataSource_LoadedData(object sender, System.Windows.Controls.LoadedDataEventArgs e)
{
var first = e.Entities.First() as BusinessApplication1.Web.Models.tableA;
var query = from tableB in first.TableBs select tableB;
System.Windows.MessageBox.Show(first.Name);
System.Windows.MessageBox.Show(query.Count().ToString());
foreach (BusinessApplication1.Web.Models.TableB tableB in query)
{
System.Windows.MessageBox.Show(tableB.Name);
}
if (e.HasError)
{
System.Windows.MessageBox.Show(e.Error.ToString(), "Load Error", System.Windows.MessageBoxButton.OK);
e.MarkErrorAsHandled();
}
}
Der Code im Loaded_Data - Ereignis fördert merkwürdigerweiße als Count() "0" zu Tage. Das kann eigentlich nicht sein. Die Tabellen sind momentan mit folgenden Werten gefüllt
Auch wenn du es mit anderen Worten ausdrücken willst bleibt es dabei. Du mußt einen Graphen mit Include() erzeugen bei denen die referenzierten B's in einer Liste an die A's hängen.
FrEEzE2046 schrieb:
Der Code im Loaded_Data - Ereignis fördert merkwürdigerwei<b>s</b>e als Count() "0" zu Tage. Das kann eigentlich nicht sein.
Warum nicht? Die B's sind doch noch gar nicht geladen. Hat das erste TableA überhaupt B-Subobjekte? Vorausgesetzt es handelt sich bei first um das erste TableA-objekt in deinem TableA-Set. Du kannst alternativ ein
C# Code:
var first = e.Entities.First() as BusinessApplication1.Web.Models.tableA;
first.TableBs.Load();
var query = from tableB in first.TableBs select tableB;
C# Code:
var first = e.Entities.First() as BusinessApplication1.Web.Models.tableA;
first.TableBs.Load();
var query = from tableB in first.TableBs select tableB;
C# Code:
var first = e.Entities.First() as BusinessApplication1.Web.Models.tableA;
first.TableBs.Load();
var query = from tableB in first.TableBs select tableB;
versuchen, aber Deferred Loading ist in diesem Fall recht teuer, weil er für jedes A nochmal einen Roundtrip zur Datenbank machen muss.
Nächstes Thema anzeigen Vorheriges Thema anzeigen
Sie können Beiträge in dieses Forum schreiben. Sie können auf Beiträge in diesem Forum antworten. Sie können Ihre Beiträge in diesem Forum nicht bearbeiten. Sie können Ihre Beiträge in diesem Forum nicht löschen. Sie können an Umfragen in diesem Forum nicht mitmachen.
c++.de ist Teilnehmer des Partnerprogramms von Amazon Europe S.à.r.l. und Partner des Werbeprogramms, das zur Bereitstellung eines Mediums
für Websites konzipiert wurde, mittels dessen durch die Platzierung von Werbeanzeigen und Links zu amazon.de
Werbekostenerstattung verdient werden kann.
Die Vervielfältigung der auf den Seiten www.c-plusplus.de, www.c-plusplus.info, www.c-sar.de, www.c-plusplus.net und www.baeckmann.de
enthaltenen Informationen ohne eine schriftliche Genehmigung des Seitenbetreibers ist untersagt
(vgl. §4 Urheberrechtsgesetz). Die Nutzung und Änderung der vorgestellten Strukturen und Verfahren in
privaten und kommerziellen Softwareanwendungen ist ausdrücklich erlaubt, soweit keine Rechte Dritter verletzt werden.
Der Seitenbetreiber übernimmt keine Gewähr für die Funktion einzelner Beiträge oder Programmfragmente, insbesondere
übernimmt er keine Haftung für eventuelle aus dem Gebrauch entstehenden Folgeschäden.