using System;
using System.Web;
using System.Data.SqlClient;
using System.Collections.Specialized;
using System.Configuration;
using System.Web.Configuration;
using System.Collections.Generic;
using System.Configuration.Provider;
using System.Security.Permissions;
using System.Data.Common;
using System.Data;
/// <summary> /// SqlSiteMapProvider /// </summary> public class SqlSiteMapProvider : StaticSiteMapProvider
{
private string _strCon;
private int _indexID, _indexTitle, _indexUrl, _indexDesc, _indexParent;
// 节点 private SiteMapNode _node;
// 节点字典表 private Dictionary<
int, SiteMapNode> _nodes =
new Dictionary<
int, SiteMapNode>();
// for 线程安全 private readonly object _lock =
new object();
/// <summary> /// 初始化 /// </summary> /// <param name="name">name</param> /// <param name="config">config</param> public override void Initialize(
string name, NameValueCollection config)
{
// 验证是否有config if (config ==
null)
throw new ArgumentNullException(
"config不能是null");
// 没有provider则设置为默认的 if (String.IsNullOrEmpty(name))
name =
"SqlSiteMapProvider";
// 没有描述就增加一个描述 if (
string.IsNullOrEmpty(config[
"description"]))
{
config.Remove(
"description");
config.Add(
"description",
"SqlSiteMapProvider");
}
// 调用基类的初始化方法 base.Initialize(name, config);
// 初始化连接字符串 string conStringName = config[
"connectionStringName"];
if (String.IsNullOrEmpty(conStringName))
throw new ProviderException(
"没找到connectionStringName");
config.Remove(
"connectionStringName");
if (WebConfigurationManager.ConnectionStrings[conStringName] ==
null)
throw new ProviderException(
"根据connectionStringName没找到连接字符串");
// 获得连接字符串 _strCon = WebConfigurationManager.ConnectionStrings[conStringName].ConnectionString;
if (String.IsNullOrEmpty(_strCon))
throw new ProviderException(
"连接字符串是空的");
}
/// <summary> /// 从持久性存储区加载站点地图信息,并在内存中构建它 /// </summary> /// <returns></returns> public override SiteMapNode BuildSiteMap()
{
lock (_lock)
{
// 线程安全的实现 if (_node !=
null)
return _node;
SqlConnection connection =
new SqlConnection(_strCon);
try {
SqlCommand command =
new SqlCommand(
"sp_GetSiteMap", connection);
command.CommandType = CommandType.StoredProcedure;
connection.Open();
SqlDataReader reader = command.ExecuteReader();
// 获得各个字段的索引 _indexID = reader.GetOrdinal(
"ID");
_indexUrl = reader.GetOrdinal(
"Url");
_indexTitle = reader.GetOrdinal(
"Title");
_indexDesc = reader.GetOrdinal(
"Description");
_indexParent = reader.GetOrdinal(
"Parent");
if (reader.Read())
{
// 把第一条记录作为根节点添加 _node = CreateSiteMapNodeFromDataReader(reader);
AddNode(_node,
null);
// 构造节点树 while (reader.Read())
{
// 在站点地图中增加一个节点 SiteMapNode node = CreateSiteMapNodeFromDataReader(reader);
AddNode(node, GetParentNodeFromDataReader(reader));
}
}
reader.Close();
}
catch (Exception ex)
{
throw new Exception(ex.ToString());
}
finally {
connection.Close();
}
// 返回SiteMapNode return _node;
}
}
/// <summary> /// 将检索目前由当前提供程序管理的所有节点的根节点 /// </summary> /// <returns></returns> protected override SiteMapNode GetRootNodeCore()
{
lock (_lock)
{
return BuildSiteMap();
}
}
/// <summary> /// 根据DataReader读出来的数据返回SiteMapNode /// </summary> /// <param name="reader">DbDataReader</param> /// <returns></returns> private SiteMapNode CreateSiteMapNodeFromDataReader(DbDataReader reader)
{
if (reader.IsDBNull(_indexID))
throw new ProviderException(
"没找到ID");
int id = reader.GetInt32(_indexID);
if (_nodes.ContainsKey(id))
throw new ProviderException(
"不能有重复ID");
// 根据字段索引获得相应字段的值 string title = reader.IsDBNull(_indexTitle) ?
null : reader.GetString(_indexTitle).Trim();
string url = reader.IsDBNull(_indexUrl) ?
null : reader.GetString(_indexUrl).Trim();
string description = reader.IsDBNull(_indexDesc) ?
null : reader.GetString(_indexDesc).Trim();
// 新建一个SiteMapNode SiteMapNode node =
new SiteMapNode(
this, id.ToString(), url, title, description);
// 把这个SiteMapNode添加进节点字典表里 _nodes.Add(id, node);
// 返回这个SiteMapNode return node;
}
/// <summary> /// 得到父节点的SiteMapNode /// </summary> /// <param name="reader"></param> /// <returns></returns> private SiteMapNode GetParentNodeFromDataReader(DbDataReader reader)
{
if (reader.IsDBNull(_indexParent))
throw new ProviderException(
"父节点不能是空");
int pid = reader.GetInt32(_indexParent);
if (!_nodes.ContainsKey(pid))
throw new ProviderException(
"有重复节点ID");
// 返回父节点的SiteMapNode return _nodes[pid];
}
}