#8 Wirklich funktionierender SqlSiteMapProvider 
von  Christopher Benge am 10.03.2008 15:03:25
Kategorie: .NET Entwicklung
Keywords: .NET ASP.NET C#
 

Dieser Artikel bezieht sich auf den MSDN Artikel "Ein SQL-SiteMapProvider für SQL Server und ASP.NET 2.0".

Wir haben den Code des Providers für das Menü unserer Hompage verwendet, mussten aber leider einige Fehler feststellen bzw. haben einige Verbesserungen hinzugefügt um das Ganze zum Laufen zu bringen.

SqlCacheDependency

Das erste Problem trat mit der Verwendung der SqlCacheDependency über das Command-Objekt auf. Um das Feature der Abhänhängigkeit vom Command-Objekt zu nutzen, muss auf der verwendeten Datenbank der Service Broker aktiviert sein.
Die kann man mit dem Datenbankbefehl

Alter Database DBName Set Enable_Broker;

erreichen.

Danach funktionierte die erste Abfrage, allerdings wurde bei einer Änderung der Daten in der Datenbank kein Event ausgelöst und die Abfrage nie neu durchgeführt.

SQL Abfrage-Syntax

Nach einigem Suchen und dem studieren der Hilfe zur SqlCacheDependency-Klasse fandenwir heraus, dass die Benachrichtigungen nur bei "einfachen Abfragen" von Tabellen funktionieren, nicht aber bei Stored Procedures wie im ursprünglichen Code.
Wir stellten den Aufruf von "proc_GetSiteMap" auf etwas wie "Select * from SiteMapData" um, um der Spezifikation in der Hilfe zu entsprechen.

Leider stellte sich immer noch nicht der gewünschte Erfolg ein.

Datenbank Kompatibilitätslevel

Nach einigem Suchen in diversen Foren war die Lösung gefunden: da die Benachrichtigungen ein neues Feature von SQL Server 2005 sind, muss der Kompatibilitätsgrad der verwendeten Datenbank auf "SQL Server 2005 (90)" gestellt werden, dann läuft alles rund.

Datenbank Schema

Die in unserer Variante verwendete Tabelle hat folgendes Schema:

CREATE TABLE [dbo].[WebContent2](
[ID] [int] NOT NULL,
[Parent] [int] NOT NULL,
[Title] [nvarchar](70) NOT NULL,
[Url] [nvarchar](70) NULL,
[Description] [nvarchar](300) NULL,
[SortOrder] [int] NOT NULL,
[ShowMenu] [bit] NOT NULL,
[ShowSitemap] [bit] NOT NULL,
[ShowNavBar] [bit] NOT NULL,
[IsKursNode] [bit] NOT NULL )
ON [PRIMARY]

Code

Nachfolgend unsere Modifikation des ursprünglichen Codes in der Methode BuildSiteMap():

public override SiteMapNode BuildSiteMap()
{
    lock (_lock)
    {
        // Return immediately if this method has been called before
        if (_root != null)
        {
            return _root;
        }
        // Query the database for site map nodes
        SqlConnection connection = new SqlConnection(_connect);
        try
        {
            SqlCommand command = new SqlCommand("Select ID, Parent, Title, Url, Description, "
                +"'' as Roles From dbo.WebContent2 Where ShowMenu = 1 Order By SortOrder Asc",
                connection);
            command.CommandType = CommandType.Text;

            // Create a SQL cache dependency if requested
            SqlCacheDependency dependency = null;
            if (_2005dependency)
                dependency = new SqlCacheDependency(command);
            else if (!String.IsNullOrEmpty(_database) && !string.IsNullOrEmpty(_table))
                dependency = new SqlCacheDependency(_database, _table);

            connection.Open();
            SqlDataReader reader = command.ExecuteReader();

            _indexID = reader.GetOrdinal("ID");
            _indexUrl = reader.GetOrdinal("Url");
            _indexTitle = reader.GetOrdinal("Title");
            _indexDesc = reader.GetOrdinal("Description");
            _indexRoles = reader.GetOrdinal("Roles");
            _indexParent = reader.GetOrdinal("Parent");

           if (reader.Read())
           {
               // Create the root SiteMapNode and add it to the site map
               _root = CreateSiteMapNodeFromDataReader(reader);
               AddNode(_root, null);

               // Build a tree of SiteMapNodes underneath the root node
               while (reader.Read())
               {
                   // Create another site map node and add it to the site map
                   SiteMapNode node = CreateSiteMapNodeFromDataReader(reader);
                   AddNode(node, GetParentNodeFromDataReader(reader));
               }

               // Use the SQL cache dependency
               if (dependency != null)
               {
                   HttpRuntime.Cache.Insert(_cacheDependencyName, new object(), dependency,
                       Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable,
                       new CacheItemRemovedCallback(OnSiteMapChanged));
               }
            }
        }
        finally
        {
            connection.Close();
        }
        // Return the root SiteMapNode
        return _root;
    }
}

 

Dateien
 
DateiGroesseErzeugtDownload
C# Code SqlSiteMapProvider 11 KB 04.04.2008 08:51:14 Download SqlSiteMapProvider.cs...
Konfigurations Beispiel 0 KB 04.04.2008 08:52:05 Download Provider.config...
Skript für Datenbank-Tabelle 2 KB 04.04.2008 08:52:54 Download WebContentTable.sql...
ASPX-Beispiel für SiteMapDataSource 0 KB 04.04.2008 08:53:36 Download SampleMenu_DataSource.aspx...

Kommentare