code it

Martins Tech Blog

25. Treffen der PASS Regionalgruppe Sachsen am 25.01.2010

5 Jahre PASS Deutschland - in Dresden wird nachgefeiert! Nachdem das eigentliche Treffen zum Thema Microsoft SQL Server 2008 R2 im September leider aufgrund von Krankheit nicht ganz wie geplant stattfinden konnte, wird der Termin nun nachgeholt.
Die PASS Regionalgruppe Dresden trifft sich am Montag den 25.01.2010 an gewohnter Stelle im IT-Trainingshaus am Waldschlösschen. Nähere Informationen zum Termin und eine Anfahrtsbeschreibung findet man auf der PASS-Seite im Bereich Regionalgruppe Sachsen.

Exam 70-630: Configuring Office SharePoint Server 2007

Da sich das Jahr nun so langsam dem Ende zuneigt, war das nun auch die letzte Prüfung für dieses Jahr. Dieses Mal war es die Zertifizierungsprüfung 70-630. Wie der Name schon sagt, ging es in den 51 Fragen um die Konfiguration und Einrichtung von MOSS 2007.

Thematisch ging es dabei um:
  • Configuring Microsoft Office SharePoint Server 2007
  • Managing Search
  • Configuring Content Management
  • Configuring Business Forms
  • Managing Business Intelligence
  • Managing Administration
  • Deploying or Upgrading

Zu den einfacheren Fragen gehörten sinngemäß: "Was sollte man tun, wenn die Suche nicht alle Ergebnisse findet?" oder "Wie bekomme ich einen Link zu einer Site in die Navigationsleiste?" Aber einige der Fragen betrachteten auch Themen, mit denen man sich nicht täglich konfrontiert sieht, wie den Search-for-broken-Links-Menüpunkt oder der Einrichtung von IRM.

Nachlese zum Treffen der .NET Usergroup Chemnitz

Am 10.12.2009 fand in Chemnitz ein Treffen der .NET Usergroup statt. Dieser Termin stand voll und ganz unter dem Thema SharePoint.

Da wir während unserer täglichen Arbeit sehr viel mit SharePoint zu tun haben und auch die SharePoint Usergroup hier in Dresden mit veranstalten, nutzten Anne Rüger, Torsten Hufsky und ich die Gelegenheit für einen Ausflug nach Chemnitz. Im TCC angekommen wurden wir sehr freundlich aufgenommen.

In einer ersten Präsentation gab ich einen kurzen Überblick über die Features von WSS 3.0 und MOSS 2007. An ein paar Beispielen zeigte ich, wie man Workspaces erstellt, Listen anlegt, mit Hilfe der Tools Central Administration und stsadm das Portal administrieren kann und im den SharePoint Designer einfache Workflows zu erzeugen. Mit dabei auch ein kleiner Ausblick auf SharePoint 2010.

Im weiteren Verlauf gaben Anne und Torsten einen kurzen Einblick, wie man serverseitig auf das Objektmodell zugreift und was man dabei beachten muss – als Stichworte hierfür: “Disposing von Objekten”, “Elevated Privileges” – und wie man von einem Client mit Hilfe der integrierten Webservices auf Listen und Webs zugreift.



Das Feedback der anderen Teilnehmer war durchweg positiv und auch wir hatten viel Spaß dabei, das Produkt vorzustellen, etwas aus dem Nähkästchen zu plaudern und spannende Themen mit denjenigen zu besprechen, die schon Erfahrungen hatten und über ähnliche Probleme gestolpert sind und Erfolgserlebnisse zu teilen.

Ich bin schon sehr gespannt und freue mich auf weitere Treffen und auf gemeinsame Themen.

Tabellen und Abfragen einer Access-OleDbConnection ermitteln

Möchte man dem Endanwender selbst die Entscheidung überlassen, welche Datenbankobjekte für eine bestimmte Operation relevant sind, so bietet es sich an, diese als Auswahl bereitzustellen und so Fehleingaben und Frust bei manueller Eingabe zu vermeiden. Das Beispiel soll zeigen, wie alle Tabellen und Abfragen einer Access 2003 Datenbank ermittelt werden können. Schnell ist herausgefunden, dass die Methode GetOleDbSchemaTable diese Aufgabe unterstützen kann - aber wie geht man damit genau um?

Tabellen ermitteln
Zunächst gilt es, alle Tabellen zu ermitteln. Im einfachsten Fall ruft man dafür

DataTable schemaTable = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);

auf, wobei "connection" eine bestehende OleDbConnection auf die fragliche Access-Datenbank ist.

Das Ergebnis ist ein DataTable. Die Spalte "TABLE_TYPE" ermöglicht eine Filterung auf die verschiedenen Objekttypen. Dabei haben Benutzertabellen den Typ "TABLE", verknüpfte Tabellen den Typ "LINK". Diese Filterung kann auch gleich beim Aufruf der Funktion durchgeführt werden, indem der zweite Parameter der Funktion GetOleDbSchemaTable mit befüllt wird. Der folgende Aufruf gibt die DataTable gefiltert nach dem Typ "TABLE" zurück.

DataTable schemaTable = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,new object[] { null, null, null, "TABLE" });

Abfragen ermitteln
Für die Ermittlung der Views gibt es mehrere Möglichkeiten. Die erste sticht direkt ins Auge - ein Aufruf von

DataTable schemaTable = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,new object[] { null, null, null, "VIEW" });

Eine weitere Möglichkeit ist, "GetOleDbSchemaTable" mit dem Parameter "OleDbSchemaGuid.Views" aufzurufen. Dabei hat der zweitgenannte Aufruf den Vorteil, dass hier die Definition der Abfrage - also der SQL-Text mit abgerufen wird.

DataTable schemaTable = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Views, null);

Bei näherer Betrachtung fällt aber auf, dass hier nicht alle Abfragen enthalten sind. Es fehlen Abfragen, die einen Parameter erwarten sowie Union- und Kreuztabellen-Abfragen. Die Lösung dieses Problems ist ein weiterer Aufruf von "GetOleDbSchemaTable" mit dem Parameter "OleDbSchemaGuid.Procedures". Darin enthalten sind alle Abfragen, die solche Besonderheiten haben.

 

Dabei erscheinen auch interne Abfragen mit. Das sind SQL-Statements, die direkt in das Feld Datenquelle eingegeben wurden ohne vorher eine Abfrage zu definieren - diese beginnen mit "~sq_" und sollten für externe Belange irrelevant sein. Bei den anderen Einträgen kann anhand selbst gewählter Kriterien entschieden werden, ob diese für externen Zugriff relevant sind oder nicht. 

Das Ergebnis 
Alle diese Erkenntnisse zusammengenommen, könnte der resultierende Quellcode ungefähr wie folgt aussehen:

private List GetDbObjectNames(string dbPath)
{
    List dbObjectsList = new List();

    string connectionString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + dbPath;

    using (OleDbConnection connection = new OleDbConnection(connectionString))
    {
        connection.Open();
        DataTable schemaTable = null;
        
        // tables
        schemaTable = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables,new object[] { null, null, null, "TABLE" });
        foreach (DataRow row in schemaTable.Rows)
        {
            dbObjectsList.Add(row["Table_Name"] as string);
        }

        // linked tables
        schemaTable = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "LINK" });
        foreach (DataRow row in schemaTable.Rows)
        {
            dbObjectsList.Add(row["Table_Name"] as string);
        }

        // views
        schemaTable = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Views, null);
        foreach (DataRow row in schemaTable.Rows)
        {
            dbObjectsList.Add(row["Table_Name"] as string);
        }

        // special views
        schemaTable = connection.GetOleDbSchemaTable(OleDbSchemaGuid.Procedures, null);
        foreach (DataRow row in schemaTable.Rows)
        {
            if (!2.Equals(row["Procedure_Type"]))
                continue;
            if (((string)row["Procedure_Name"]).StartsWith("~sq_"))
                continue;
            dbObjectsList.Add(row["Procedure_Name"] as string);
        }


        connection.Close();
    }


    return dbObjectsList;
}


private void loadObjectsButton_Click(object sender, EventArgs e)
{
    dbObjectsList.Items.Clear();
    List items = GetDbObjectNames("C:\\Program Files\\Microsoft Office\\OFFICE11\\SAMPLES\\nordwind.mdb");
    dbObjectsList.Items.AddRange(items.ToArray());
}