Bibliotekom – zasadniczo – nie pomaga tajemniczość (o dezinformacji w temacie relacji)
W ADO.NET jest coś takiego jak możliwość ustanowienia relacji pomiędzy dwiema tabelami, a następnie prezentacja tabeli zależnej z kontekście nadrzędnej. Można to zrealizować np. tak:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using System.Data.SqlClient; namespace DBTest { public partial class Form1 : Form { private SqlConnection conSQL = new SqlConnection(); private DataSet ds; public Form1() { InitializeComponent(); } private string MakeConnectionString() { conSQL.Close(); return "Persist Security Info=False;Data Source=.\\SQLEXPRESS2K8R2;Integrated Security=SSPI;"; } private void MakeParameter(SqlCommand cmd, string Name, SqlDbType type, ParameterDirection pd, int size, string value) { SqlParameter p = cmd.Parameters.Add(Name, type); if (size > 0) p.Size = size; p.Direction = pd; if (value == null) p.Value = System.DBNull.Value; else p.Value = value; } private void button1_Click(object sender, EventArgs e) { if (conSQL.State != ConnectionState.Open) { conSQL.ConnectionString = MakeConnectionString(); conSQL.Open(); } string SQL = " create table #Elementy(id int, nazwa varchar(50));\n" + " insert into #Elementy values (1, 'Pierwszy');\n" + " insert into #Elementy values (2, 'Pierwszy dla pierwszego');\n" + " insert into #Elementy values (3, 'Drugi dla pierwszego');\n" + " insert into #Elementy values (4, 'Trzeci dla pierwszego');\n" + " insert into #Elementy values (6, 'Drugi');\n" + " insert into #Elementy values (7, 'Pierwszy dla drugiego');\n" + " insert into #Elementy values (8, 'Drugi dla drugiego');\n" + " create table #Składniki (id int identity(1, 1), ZestawId int, SkładnikId int);\n" + " insert into #Składniki values (1, 2);\n" + " insert into #Składniki values (1, 3);\n" + " insert into #Składniki values (1, 4);\n" + " insert into #Składniki values (6, 7);\n" + " insert into #Składniki values (6, 8);\n" + " select *\n" + // przekaż pełną listę elementów (zarówno składniki jak i zestawy) " from #Elementy;\n" + " select S.*, E.nazwa\n" + // przekaż jedynie składniki i ich związki z zestawami " from #Składniki S\n" + " inner join #Elementy E on E.id = S.SkładnikId;"; SqlCommand cmd = new SqlCommand(SQL, conSQL); cmd.CommandType = CommandType.Text; SqlDataAdapter da = new SqlDataAdapter(cmd); ds = new DataSet(); // nowy obiekt na wyniki działania procedury da.Fill(ds); // wypełnij obiekt wynikami // ustanowienie relacji ds.Relations.Add("relation", ds.Tables[0].Columns["id"], ds.Tables[1].Columns["ZestawId"]); // przypisanie do gridów źródła danych MainGrid.DataSource = ds;//.Tables[0]; DependendGrid.DataSource = ds;//.Tables[0]; // wkazanie elementu, którego dane mają być prezentowane MainGrid.DataMember = ds.Tables[0].TableName; // wkazanie elementu, którego dane mają być prezentowane DependendGrid.DataMember = ds.Tables[0].TableName + ".relation"; } } }
Jest to kod aplikacji WinForms. Ostatnie dwie instrukcje metody button1_Click umożliwiają wskazanie danych, które mają zostać zaprezentowane na gridach. Zgodnie z definicją właściwości DataMember służy ona do wskazania (lub odczytania) nazwy listy lub tabeli, którą grid ma prezentować. Coś tu jednak nie gra. W ostatniej instrukcji nie jest bowiem wskazywana ani lista, ani tabela zawierająca dane. Jest wskazywana nazwa relacji. Co ciekawe występuje ona w kontekście nazwy tabeli, tej samej, której zawartość jest wyświetlana w MainGrid. A jednak koniec końców grid skądś wie, że ma wyświetlić nie tę właśnie tabelę, ale tabelę, która jest z nią w relacji i to jedynie w zakresie, jaki ta relacja w danej chwili definiuje. Proszę także zauważyć, że relacja został zdefiniowana w ramach DataSetu ds, a nie pierwszej jego tabeli. A jednak jest ona podawana właśnie w jej kontekście.
Przekopałem MSDN, aby odnaleźć jakieś informacje uzupełniające przeznaczenie właściwości DataMember i … nic. Wygląda na to, że jest to swojego rodzaju magiczna właściwość, której wszystkie możliwości nie są znane. Być może potrafi ona więcej cudownych rzeczy, niż tylko wskazywanie tabeli lub listy z danymi albo tabeli podrzędnej (w dodatku nie bezpośrednio, a przez wskazanie relacji). Pozostaje chyba zajrzeć do źródeł .NET, co pewnie w stosownym momencie uczynię. Na razie jednak „oczywistość” sposobu na prezentację zawartości tabeli zależnej będzie dla mnie niezgłębioną tajemnicą.