Vs2005的SiteMapProvider的SQL实现
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Data;
using System.Data.SqlClient;
using System.Security.Permissions;
using System.Web;namespace UrlLibrary
{
    [AspNetHostingPermission(SecurityAction.Demand, Level=AspNetHostingPermissionLevel.Minimal)]
    public class SQLSiteMapProvider : StaticSiteMapProvider
    {
        private SiteMapNode rootNode =  null;
        private SqlConnection sqlConnection = null;        // This string is case sensitive.
        private string SqlConnectionStringName = "SqlConnectionStringName";        // Implement a default constructor.
        public SQLSiteMapProvider() { }        // 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[SqlConnectionStringName];            if (null == connectionString || connectionString.Length == 0)
                throw new Exception ("The connection string was not found.";
            else
                sqlConnection = new SqlConnection(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 (sqlConnection.State == ConnectionState.Closed)
                        sqlConnection.Open();
                    SqlCommand rootNodeCommand = new SqlCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid IS NULL",
                                         sqlConnection);
                    SqlDataReader 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.
                    SqlCommand childNodesCommand = new SqlCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid = ?",
                                         sqlConnection);
                    SqlParameter rootParam = new SqlParameter("parentid", SqlDbType.Int);
                    rootParam.Value = rootNodeId;
                    childNodesCommand.Parameters.Add(rootParam);                    SqlDataReader 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();
                    sqlConnection.Close();
                }
                return rootNode;
            }
        }
    }
}
上面是Vs2005的SiteMapProvider的SQL实现的程序,我想肯定有人用过,请高手解释一下其中的这句:SqlCommand childNodesCommand = new SqlCommand("SELECT nodeid, url, name FROM SiteMap WHERE parentnodeid = ?",sqlConnection);中的问号(?)是什么意思?该怎么实现?还有这句: SqlParameter rootParam = new SqlParameter("parentid", SqlDbType.Int);中的parentid是数据表中的哪个字段?如果哪位能给个实例的源码就更好(含数据库)。