共用方式為


Access 網站導覽提供者範例

更新:2007 年 11 月

說明完整的 Access 網站導覽提供者。

範例

描述

下列程式碼範例示範如何擴展 StaticSiteMapProvider 類別,以便使用 Microsoft Access 當做網站導覽提供者。網站導覽提供者使用 .NET Framework Data Provider for OLE DB 連接 Access 資料庫。

程式碼

Imports System
Imports System.Collections
Imports System.Collections.Specialized
Imports System.Data
Imports System.Data.OleDb
Imports System.Security.Permissions
Imports System.Web

Namespace Samples.AspNet.VB.Controls

    ' An extremely simple AccessSiteMapProvider that only supports a
    ' site map node hierarchy one level deep.
    <AspNetHostingPermission(SecurityAction.Demand, Level:=AspNetHostingPermissionLevel.Minimal)> _
    Public Class AccessSiteMapProvider
        Inherits StaticSiteMapProvider

        Private aRootNode As SiteMapNode = Nothing
        Private accessConnection As OleDbConnection = Nothing

        ' This string is case sensitive.
        Private AccessConnectionStringName As String = "accessSiteMapConnectionString"

        ' Implement a default constructor.
        Public Sub New()
        End Sub 'New

        ' Some basic state to help track the initialization state of the provider.
        Private initialized As Boolean = False

        Public Overridable ReadOnly Property IsInitialized() As Boolean
            Get
                Return initialized
            End Get
        End Property

        ' Return the root node of the current site map.
        Public Overrides ReadOnly Property RootNode() As SiteMapNode
            Get
                Return BuildSiteMap()
            End Get
        End Property

        Protected Overrides Function GetRootNodeCore() As SiteMapNode
            Return RootNode
        End Function

        ' Initialize is used to initialize the properties and any state that the
        ' AccessProvider holds, but is not used to build the site map.
        ' The site map is built when the BuildSiteMap method is called.
        Public Overrides Sub Initialize(ByVal name As String, ByVal attributes As NameValueCollection)
            If IsInitialized Then
                Return
            End If
            MyBase.Initialize(name, attributes)

            ' Create and test the connection to the Microsoft Access database.
            ' Retrieve the Value of the Access connection string from the
            ' attributes NameValueCollection.
            Dim connectionString As String = attributes(AccessConnectionStringName)

            If Nothing = connectionString OrElse connectionString.Length = 0 Then
                Throw New Exception("The connection string was not found.")
            Else
                accessConnection = New OleDbConnection(connectionString)
            End If
            initialized = True
        End Sub 'Initialize

        ' SiteMapProvider and StaticSiteMapProvider methods that this derived class must override.
        '
        ' Clean up any collections or other state that an instance of this may hold.
        Protected Overrides Sub Clear()
            SyncLock Me
                aRootNode = Nothing
                MyBase.Clear()
            End SyncLock
        End Sub 'Clear

        ' Build an in-memory representation from persistent
        ' storage, and return the root node of the site map.
        Public Overrides Function BuildSiteMap() As SiteMapNode

            ' Since the SiteMap class is static, make sure that it is
            ' not modified while the site map is built.
            SyncLock Me

                ' If there is no initialization, this method is being
                ' called out of order.
                If Not IsInitialized Then
                    Throw New Exception("BuildSiteMap called incorrectly.")
                End If

                ' If there is no root node, then there is no site map.
                If aRootNode Is Nothing Then
                    ' Start with a clean slate
                    Clear()

                    ' Select the root node of the site map from Microsoft Access.
                    Dim rootNodeId As Integer = -1

                    If accessConnection.State = ConnectionState.Closed Then
                        accessConnection.Open()
                    End If
                    Dim rootNodeCommand As New OleDbCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid IS NULL", accessConnection)
                    Dim rootNodeReader As OleDbDataReader = rootNodeCommand.ExecuteReader()

                    If rootNodeReader.HasRows Then
                        rootNodeReader.Read()
                        rootNodeId = rootNodeReader.GetInt32(0)
                        ' Create a SiteMapNode that references the current StaticSiteMapProvider.
                        aRootNode = New SiteMapNode(Me, rootNodeId.ToString(), rootNodeReader.GetString(1), rootNodeReader.GetString(2))
                    Else
                        Return Nothing
                    End If
                    rootNodeReader.Close()
                    ' Select the child nodes of the root node.
                    Dim childNodesCommand As New OleDbCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid = ?", accessConnection)
                    Dim rootParam As New OleDbParameter("parentid", OleDbType.Integer)
                    rootParam.Value = rootNodeId
                    childNodesCommand.Parameters.Add(rootParam)

                    Dim childNodesReader As OleDbDataReader = childNodesCommand.ExecuteReader()

                    If childNodesReader.HasRows Then

                        Dim childNode As SiteMapNode = Nothing
                        While childNodesReader.Read()
                            childNode = New SiteMapNode(Me, _
                            childNodesReader.GetInt32(0).ToString(), _
                            childNodesReader.GetString(1), _
                            childNodesReader.GetString(2))

                            ' Use the SiteMapNode AddNode method to add
                            ' the SiteMapNode to the ChildNodes collection.
                            AddNode(childNode, aRootNode)
                        End While
                    End If

                    childNodesReader.Close()
                    accessConnection.Close()
                End If
                Return aRootNode
            End SyncLock

        End Function 'BuildSiteMap

    End Class 'AccessSiteMapProvider

End Namespace
namespace Samples.AspNet.CS.Controls {

    using System;
    using System.Collections;
    using System.Collections.Specialized;
    using System.Data;
    using System.Data.OleDb;
    using System.Security.Permissions;
    using System.Web;

    /// An extremely simple AccessSiteMapProvider that only supports a
    /// site map node hierarchy 1 level deep.
    [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Minimal)]
    public class AccessSiteMapProvider : StaticSiteMapProvider
    {
        private SiteMapNode rootNode =  null;
        private OleDbConnection accessConnection = null;

        // This string is case sensitive.
        private string AccessConnectionStringName = "accessSiteMapConnectionString";

        // Implement a default constructor.
        public AccessSiteMapProvider () { }

        // Some basic state to help track the initialization state of the provider.
        private bool initialized = false;
        public virtual bool IsInitialized {
            get {
                return initialized;
            }
        }
        // Return the root node of the current site map.
        public override SiteMapNode RootNode {
            get {
                SiteMapNode temp = null;
                temp = BuildSiteMap();
                return temp;
            }
        }
        protected override SiteMapNode GetRootNodeCore() {
            return RootNode;
        }
        // Initialize is used to initialize the properties and any state that the
        // AccessProvider holds, but is not used to build the site map.
        // The site map is built when the BuildSiteMap method is called.
        public override void Initialize(string name, NameValueCollection attributes) {
            if (IsInitialized)
                return;

            base.Initialize(name, attributes);

            // Create and test the connection to the Microsoft Access database.

            // Retrieve the Value of the Access connection string from the
            // attributes NameValueCollection.
            string connectionString = attributes[AccessConnectionStringName];

            if (null == connectionString || connectionString.Length == 0)
                throw new Exception ("The connection string was not found.");
            else
                accessConnection = new OleDbConnection(connectionString);

            initialized = true;
        }

        ///
        /// SiteMapProvider and StaticSiteMapProvider methods that this derived class must override.
        ///
        // Clean up any collections or other state that an instance of this may hold.
        protected override void Clear() {
            lock (this) {
                rootNode = null;
                base.Clear();
            }
        }

        // Build an in-memory representation from persistent
        // storage, and return the root node of the site map.
        public override SiteMapNode BuildSiteMap() {

            // Since the SiteMap class is static, make sure that it is
            // not modified while the site map is built.
            lock(this) {

                // If there is no initialization, this method is being
                // called out of order.
                if (! IsInitialized) {
                    throw new Exception("BuildSiteMap called incorrectly.");
                }

                // If there is no root node, then there is no site map.
                if (null == rootNode) {
                    // Start with a clean slate
                    Clear();

                    // Select the root node of the site map from Microsoft Access.
                    int rootNodeId = -1;

                    if (accessConnection.State == ConnectionState.Closed)
                        accessConnection.Open();
                    OleDbCommand rootNodeCommand =
                        new OleDbCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid IS NULL",
                                         accessConnection);
                    OleDbDataReader rootNodeReader = rootNodeCommand.ExecuteReader();

                    if(rootNodeReader.HasRows) {
                        rootNodeReader.Read();
                        rootNodeId = rootNodeReader.GetInt32(0);
                        // Create a SiteMapNode that references the current StaticSiteMapProvider.
                        rootNode   = new SiteMapNode(this,
                                                     rootNodeId.ToString(),
                                                     rootNodeReader.GetString(1),
                                                     rootNodeReader.GetString(2));

                    }
                    else return null;

                    rootNodeReader.Close();
                    // Select the child nodes of the root node.
                    OleDbCommand childNodesCommand =
                        new OleDbCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid = ?",
                                         accessConnection);
                    OleDbParameter rootParam = new OleDbParameter("parentid", OleDbType.Integer);
                    rootParam.Value = rootNodeId;
                    childNodesCommand.Parameters.Add(rootParam);

                    OleDbDataReader childNodesReader = childNodesCommand.ExecuteReader();

                    if (childNodesReader.HasRows) {

                        SiteMapNode childNode = null;
                        while(childNodesReader.Read()) {
                            childNode =  new SiteMapNode(this,
                                                         childNodesReader.GetInt32(0).ToString(),
                                                         childNodesReader.GetString(1),
                                                         childNodesReader.GetString(2));

                            // Use the SiteMapNode AddNode method to add
                            // the SiteMapNode to the ChildNodes collection.
                            AddNode(childNode, rootNode);
                        }
                    }

                    childNodesReader.Close();
                    accessConnection.Close();
                }
                return rootNode;
            }
        }
    }
}
#using <System.Data.dll>
#using <System.Transactions.dll>
#using <System.EnterpriseServices.dll>
#using <System.dll>
#using <System.Web.dll>
#using <System.Configuration.dll>

using namespace System;
using namespace System::Collections;
using namespace System::Collections::Specialized;
using namespace System::Configuration;
using namespace System::Data;
using namespace System::Data::OleDb;
using namespace System::Security::Permissions;
using namespace System::Web;

/// An extremely simple AccessSiteMapProvider that only supports a
/// site map node hierarchy 1 level deep.

[AspNetHostingPermission(SecurityAction::Demand,Level=AspNetHostingPermissionLevel::Minimal)]
public ref class AccessSiteMapProvider: public StaticSiteMapProvider
{
private:
   SiteMapNode ^ rootNode;
   OleDbConnection^ accessConnection;

   // This string is case sensitive.
   String^ AccessConnectionStringName;

public:
   // Implement a default constructor.
   AccessSiteMapProvider()
   {
      initialized = false;
      AccessConnectionStringName = "accessSiteMapConnectionString";
   }


private:

   // Some basic state to help track the initialization state of the provider.
   bool initialized;

public:

   property bool IsInitialized 
   {
      virtual bool get()
      {
         return initialized;
      }

   }

   property SiteMapNode ^ RootNode 
   {

      // Return the root node of the current site map.
      virtual SiteMapNode ^ get() override
      {
         SiteMapNode ^ temp = nullptr;
         temp = BuildSiteMap();
         return temp;
      }

   }

protected:

   virtual SiteMapNode ^ GetRootNodeCore() override
   {
      return RootNode;
   }


public:

   // Initialize is used to initialize the properties and any state that the
   // AccessProvider holds, but is not used to build the site map.
   // The site map is built when the BuildSiteMap method is called.
   virtual void Initialize( String^ name, NameValueCollection^ attributes ) override
   {
      if ( IsInitialized )
            return;

      StaticSiteMapProvider::Initialize( name, attributes );

      // Create and test the connection to the Microsoft Access database.
      // Retrieve the Value of the Access connection string from the
      // attributes NameValueCollection.
      String^ connectionString = attributes[ AccessConnectionStringName ];
      if ( nullptr == connectionString || connectionString->Length == 0 )
            throw gcnew Exception( "The connection string was not found." );
      else
            accessConnection = gcnew OleDbConnection( connectionString );

      initialized = true;
   }


protected:

   ///
   /// SiteMapProvider and StaticSiteMapProvider methods that this derived class must override.
   ///
   // Clean up any collections or other state that an instance of this may hold.
   virtual void Clear() override
   {
      System::Threading::Monitor::Enter( this );
      try
      {
         rootNode = nullptr;
         StaticSiteMapProvider::Clear();
      }
      finally
      {
         System::Threading::Monitor::Exit( this );
      }

   }


public:

   // Build an in-memory representation from persistent
   // storage, and return the root node of the site map.
   virtual SiteMapNode ^ BuildSiteMap() override
   {
      // Since the SiteMap class is static, make sure that it is
      // not modified while the site map is built.
      System::Threading::Monitor::Enter( this );
      try
      {

         // If there is no initialization, this method is being
         // called out of order.
         if (  !IsInitialized )
         {
            throw gcnew Exception( "BuildSiteMap called incorrectly." );
         }

         // If there is no root node, then there is no site map.
         if ( nullptr == rootNode )
         {

            // Start with a clean slate
            Clear();

            // Select the root node of the site map from Microsoft Access.
            int rootNodeId = -1;
            if ( accessConnection->State == ConnectionState::Closed )
               accessConnection->Open();

            OleDbCommand^ rootNodeCommand = gcnew OleDbCommand
               ("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid IS NULL", accessConnection);
            OleDbDataReader^ rootNodeReader = rootNodeCommand->ExecuteReader();
            if ( rootNodeReader->HasRows )
            {
               rootNodeReader->Read();
               rootNodeId = rootNodeReader->GetInt32( 0 );

               // Create a SiteMapNode that references the current StaticSiteMapProvider.
               rootNode = gcnew SiteMapNode(this, rootNodeId.ToString(), 
                  rootNodeReader->GetString( 1 ),rootNodeReader->GetString( 2 ));
            }
            else
               return nullptr;
            rootNodeReader->Close();

            // Select the child nodes of the root node.
            OleDbCommand^ childNodesCommand = gcnew OleDbCommand
               ("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid = ?", accessConnection);
            OleDbParameter^ rootParam = gcnew OleDbParameter( "parentid", OleDbType::Integer);
            rootParam->Value = rootNodeId;
            childNodesCommand->Parameters->Add( rootParam );
            OleDbDataReader^ childNodesReader = childNodesCommand->ExecuteReader();
            if ( childNodesReader->HasRows )
            {
               SiteMapNode ^ childNode = nullptr;
               while ( childNodesReader->Read() )
               {
                  childNode = gcnew SiteMapNode( this, 
                      System::Convert::ToString(childNodesReader->GetInt32( 0 )),
                     childNodesReader->GetString( 1 ),
                     childNodesReader->GetString( 2 ) 
                  );
                  // Use the SiteMapNode AddNode method to add
                  // the SiteMapNode to the ChildNodes collection.
                  AddNode( childNode, rootNode );
               }
            }
            childNodesReader->Close();
            accessConnection->Close();
         }
         return rootNode;
      }
      finally
      {
         System::Threading::Monitor::Exit( this );
      }

   }

};

package Samples.AspNet.JSL;
import System.*;
import System.Collections.*;
import System.Collections.Specialized.*;
import System.Data.*;
import System.Data.OleDb.*;
import System.Web.*;
import System.Configuration.*;

/// An extremely simple AccessSiteMapProvider that only supports a
/// site map node hierarchy 1 level deep.
public class AccessSiteMapProvider extends StaticSiteMapProvider
{
    private SiteMapNode rootNode = null;
    private OleDbConnection accessConnection = null;

    // This string is case sensitive.
    public String accessConnectionStringName = "accessSiteMapConnectionString";

    // Implement a default constructor.
    public AccessSiteMapProvider()
    {
    } //AccessSiteMapProvider 

    // Some basic state to help track the initialization state of the provider.
    private boolean initialized = false;

    /** @property 
     */
    public boolean get_IsInitialized()
    {
        return initialized;
    } //get_IsInitized.

    // Return the root node of the current site map.
    /** @property 
     */
    public SiteMapNode get_RootNode() throws Exception
    {
        SiteMapNode temp = null;
        temp = BuildSiteMap();
        return temp;
    } //get_RootNode

    // Initialize is used to initialize the properties and any state that the
    // AccessProvider holds, but is not used to build the site map.
    // The site map is built when the BuildSiteMap method is called.
    public void Initialize(String name, NameValueCollection attributes) 
        throws Exception
    {
        if (get_IsInitialized())
        {
            return;
        }

        super.Initialize(name, attributes);
        // Create and test the connection to the Microsoft Access database.
        // Retrieve the Value of the Access connection string from the
        // attributes NameValueCollection.
        String connectionString = attributes.get_Item(
            accessConnectionStringName);

        if (null == connectionString || connectionString.get_Length() == 0)
        {
            throw new Exception("The connection string was not found.");
        }
        else
        {
            accessConnection = new OleDbConnection(connectionString);
        }
        initialized = true;
    } //Initialize

    ///
    /// SiteMapProvider and StaticSiteMapProvider methods that this 
    /// derived class must override.
    ///
    // Clean up any collections or other state that an instance of this may hold.
    protected void Clear()
    {
        synchronized (this)
        {
            rootNode = null;
            super.Clear();
        }
    } //Clear

    // Build an in-memory representation from persistent
    // storage, and return the root node of the site map.
    public SiteMapNode BuildSiteMap() throws Exception
    {
        // Since the SiteMap class is static, make sure that it is
        // not modified while the site map is built.
        synchronized (this)
        {
            // If there is no initialization, this method is being
            // called out of order.
            if (!get_IsInitialized())
            {
                throw new Exception("BuildSiteMap called incorrectly.");
            }
            // If there is no root node, then there is no site map.
            if (null == rootNode)
            {
                // Start with a clean slate
                Clear();
                // Select the root node of the site map from Microsoft Access.
                int rootNodeId = -1;

                if (accessConnection.get_State().Equals(ConnectionState.Closed))
                {
                    accessConnection.Open();
                }

                OleDbCommand rootNodeCommand = new OleDbCommand(
                    "SELECT nodeid, url, name FROM SiteMap WHERE "
                    + "parentnodeid IS NULL", accessConnection);
                OleDbDataReader rootNodeReader = rootNodeCommand.ExecuteReader();

                if (rootNodeReader.get_HasRows())
                {
                    rootNodeReader.Read();
                    rootNodeId = rootNodeReader.GetInt32(0);
                    // Create a SiteMapNode that references the current 
                    // StaticSiteMapProvider.
                    rootNode = new SiteMapNode(this,
                        ((Int32)rootNodeId).ToString(), rootNodeReader.
                        GetString(1), rootNodeReader.GetString(2));
                }
                else
                {
                    return null;
                }
                rootNodeReader.Close();
                // Select the child nodes of the root node.
                OleDbCommand childNodesCommand = new OleDbCommand(
                    "SELECT nodeid, url, name FROM SiteMap WHERE "
                    + "parentnodeid = ?", accessConnection);
                OleDbParameter rootParam = new OleDbParameter("parentid",
                    OleDbType.Integer);
                rootParam.set_Value((Int32)rootNodeId);
                childNodesCommand.get_Parameters().Add(rootParam);

                OleDbDataReader childNodesReader = childNodesCommand.
                    ExecuteReader();

                if (childNodesReader.get_HasRows())
                {
                    SiteMapNode childNode = null;
                    while (childNodesReader.Read())
                    {
                        childNode = new SiteMapNode(this,
                            Convert.ToString(childNodesReader.GetInt32(0)), 
                            childNodesReader.GetString(1),
                            childNodesReader.GetString(2));
                        // Use the SiteMapNode AddNode method to add
                        // the SiteMapNode to the ChildNodes collection.
                        AddNode(childNode, rootNode);
                    }
                }

                childNodesReader.Close();
                accessConnection.Close();
            }
            return rootNode;
        }
    } //BuildSiteMap

    protected SiteMapNode GetRootNodeCore()
    {
        return null;
    } //GetRootNodeCore
} //AccessSiteMapProvider 

註解

若要建立先前程式碼範例用來做為網站導覽資料存放區的 Access 資料表,請在新的或現有的 Access 資料庫中發出下列資料定義查詢,然後以 Sitemap.mdb 的檔案名稱儲存 Access 資料庫。

CREATE TABLE SiteMap
(
  URL Text (255) UNIQUE,
  NAME Text (255) NOT NULL,
  PARENTNODEID Int32,
    CONSTRAINT NODEID PRIMARY KEY (URL, NAME)
)

以下列資料填入 (Populate) 資料表,並列出您建立之網站或檔案中所擁有的檔案。下表顯示範例檔案清單。

NODEID

URL

NAME

PARENTNODEID

1

Default.aspx

預設值

null (空儲存格)

2

Catalog.aspx

目錄

1

3

Aboutus.aspx

請與我們連絡

1

注意事項:

因為資料來源包含不同的 SQL 語法,某些命令可以在某個資料來源中使用,但是無法在別的資料來源中使用。因此,即使您使用 .NET Framework Data Provider for ODBC 或 .NET Framework Data Provider for OLE DB 存取資料來源 (例如,SybaseSiteMapProvider、OracleSiteMapProvider 等等),還是建議您為資料來源建立特定的網站導覽提供者。

AccessSiteMapProvider 類別衍生自 StaticSiteMapProvider 類別,並且使用基本 SQL 查詢以及 OleDbCommandOleDbDataReader 物件,從 Access 資料庫擷取資訊。

最後,在 Web.config 檔中會將 AccessSiteMapProvider 設定為預設提供者,如下列程式碼範例所示。

<configuration>
  <system.web>
    <siteMap defaultProvider="AccessSiteMapProvider">
      <providers>
        <add 
          name="AccessSiteMapProvider"
          type="<type name>"
          accessSiteMapConnectionString="PROVIDER=MICROSOFT.JET.OLEDB.4.0;DATA SOURCE=<path>\sitemap.mdb "/>
      </providers> 
    </siteMap>
  </system.web>
</configuration>

若要自訂此範例,請以實作網站導覽資料提供者之類別的完整限定名稱,取代 <type name>。例如,在上述 C# 程式碼中,您會將 <type name> 替換成 Samples.AspNet.CS.Controls.AccessSiteMapProvider。如果您編譯網站導覽資料提供者程式碼並將它放在 Bin 目錄中,則 <type name> 字串也必須包含所編譯的檔案名稱 (但不含副檔名)。例如,如果將上述 C# 程式碼編譯成名為 Samples.AspNet.dll 的檔案,則您要將 <type name> 替換成 Samples.AspNet.CS.Controls.AccessSiteMapProvider.Samples.AspNet。最後再以網站導覽資料庫的絕對實際路徑取代 <path>。

注意事項:

當您繼承自 StaticSiteMapProvider 時,您必須覆寫下列成員:BuildSiteMapGetRootNodeCore

健全的程式設計

如果您準備擴展 StaticSiteMapProvider 類別,最重要的三個方法是 GetRootNodeCoreInitializeBuildSiteMapClearFindSiteMapNode 方法有足夠讓大部分自訂提供者實作使用的預設實作。

請參閱

概念

ASP.NET 網站巡覽概觀

設定 ASP.NET 網站巡覽的安全性

設定資料存取的安全性

參考

StaticSiteMapProvider

SiteMapProvider

BuildSiteMap

OleDbCommand

OleDbDataReader

SiteMapNode

SiteMap

其他資源

裝載環境中 ASP.NET 應用程式的安全性