using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Text;
using System.Web;
using System.Data;
using System.Web.Caching;
using System.Data.SqlClient;
using System.Configuration.Provider;
using System.Data.Common;
using System.Configuration;
using System.Web.Security;
using System.Web.Configuration;
using System.Security.Permissions;
namespace FStudio.Provider
{
[SqlClientPermission(SecurityAction.Demand, Unrestricted = true)]
public class SqlSiteMapProvider : StaticSiteMapProvider
{
private const string _errmsg1 = "Missing node code";
private const string _errmsg2 = "Duplicate node code";
private const string _errmsg3 = "Missing parent code";
private const string _errmsg4 = "Invalid parent code";
private const string _errmsg5 = "Empty or missing connectionStringName";
private const string _errmsg6 = "Missing connection string";
private const string _errmsg7 = "Empty connection string";
private const string _errmsg8 = "Invalid sqlCacheDependency";
private const string _errmsg9 = "Invalid Parent Code Length";
private const string _cacheDependencyName = "__SiteMapCacheDependency";
private string _connect; // Database connection string
private string _database, _table; // Database info for SQL Server 7/2000 cache dependency
private bool _2005dependency = false; // Database info for SQL Server 2005 cache dependency
private int _indexCode, _indexClassName, _indexUrl, _indexInfo, _indexRoles, _indexTarget;
private Dictionary<string, SiteMapNode> _nodes = new Dictionary<string, SiteMapNode>(16);
private readonly object _lock = new object();
private SiteMapNode _root;
private int _codeLength = 4;
public override void Initialize(string name, NameValueCollection config)
{
// Verify that config isn't null
if (config == null)
throw new ArgumentNullException("config");
// Assign the provider a default name if it doesn't have one
if (String.IsNullOrEmpty(name))
name = "SqlSiteMapProvider";
// Add a default "description" attribute to config if the
// attribute doesn't exist or is empty
if (string.IsNullOrEmpty(config["description"]))
{
config.Remove("description");
config.Add("description", "SQL site map provider");
}
// Call the base class's Initialize method
base.Initialize(name, config);
// Initialize _connect
string connect = config["connectionStringName"];
if (String.IsNullOrEmpty(connect))
throw new ProviderException(_errmsg5);
config.Remove("connectionStringName");
if (WebConfigurationManager.ConnectionStrings[connect] == null)
throw new ProviderException(_errmsg6);
_connect = WebConfigurationManager.ConnectionStrings[connect].ConnectionString;
if (String.IsNullOrEmpty(_connect))
throw new ProviderException(_errmsg7);
// Initialize SQL cache dependency info
string dependency = config["sqlCacheDependency"];
if (!String.IsNullOrEmpty(dependency))
{
if (String.Equals(dependency, "CommandNotification", StringComparison.InvariantCultureIgnoreCase))
{
SqlDependency.Start(_connect);
_2005dependency = true;
}
else
{
// If not "CommandNotification", then extract database and table names
string[] info = dependency.Split(new char[] { ':' });
if (info.Length != 2)
throw new ProviderException(_errmsg8);
_database = info[0];
_table = info[1];
}
config.Remove("sqlCacheDependency");
}
// SiteMapProvider processes the securityTrimmingEnabled
// attribute but fails to remove it. Remove it now so we can
// check for unrecognized configuration attributes.
if (config["securityTrimmingEnabled"] != null)
config.Remove("securityTrimmingEnabled");
// Throw an exception if unrecognized attributes remain
if (config.Count > 0)
{
string attr = config.GetKey(0);
if (!String.IsNullOrEmpty(attr))
throw new ProviderException("Unrecognized attribute: " + attr);
}
}
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("SqlSiteMap_Query", connection);
command.CommandType = CommandType.StoredProcedure;
// 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();
_indexCode = reader.GetOrdinal("Code");
_indexUrl = reader.GetOrdinal("Url");
_indexClassName = reader.GetOrdinal("ClassName");
_indexInfo = reader.GetOrdinal("Info");
_indexRoles = reader.GetOrdinal("Roles");
_indexTarget = reader.GetOrdinal("Target");
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;
}
}
protected override SiteMapNode GetRootNodeCore()
{
lock (_lock)
{
BuildSiteMap();
return _root;
}
}
public override bool IsAccessibleToUser(HttpContext context, SiteMapNode node)
{
bool isUserInRole = false;
System.Collections.IList test = node.Roles;
if (node.Roles != null && (string)(node.Roles[0]) != "*")
{
// Create a SiteMapNode
foreach (string role in node.Roles)
{
if (Roles.IsUserInRole(role))
{
isUserInRole = true;
break;
}
}
}
else
{
isUserInRole = true;
}
return isUserInRole;
//return base.IsAccessibleToUser(context, node);
}
// Helper methods
private SiteMapNode CreateSiteMapNodeFromDataReader(DbDataReader reader)
{
// Make sure the node Code is present
if (reader.IsDBNull(_indexCode))
throw new ProviderException(_errmsg1);
// Get the node Code from the DataReader
string code = reader.GetString(_indexCode);
// Make sure the node Code is unique
if (_nodes.ContainsKey(code))
throw new ProviderException(_errmsg2);
// Get title, URL, description, and roles from the DataReader
string className = reader.IsDBNull(_indexClassName) ? null : reader.GetString(_indexClassName).Trim();
string url = reader.IsDBNull(_indexUrl) ? null : reader.GetString(_indexUrl).Trim();
string info = reader.IsDBNull(_indexInfo) ? null : reader.GetString(_indexInfo).Trim();
string roles = reader.IsDBNull(_indexRoles) ? null : reader.GetString(_indexRoles).Trim();
string target = reader.IsDBNull(_indexTarget) ? null : reader.GetString(_indexTarget).Trim();
// If roles were specified, turn the list into a string array
string[] rolelist = null;
if (!String.IsNullOrEmpty(roles))
rolelist = roles.Split(new char[] { ',', ';' }, 512);
// Create a SiteMapNode
NameValueCollection targetAttribute = new NameValueCollection();
targetAttribute.Add("target", target);
SiteMapNode node = new SiteMapNode(this, code, url, className, info, rolelist, targetAttribute, null, null);
// Record the node in the _nodes dictionary
_nodes.Add(code, node);
// Return the node
return node;
}
private SiteMapNode GetParentNodeFromDataReader(DbDataReader reader)
{
// Make sure the parent Code is present
if (reader.IsDBNull(_indexCode))
throw new ProviderException(_errmsg3);
// Get the parent code from the DataReader
string code = reader.GetString(_indexCode);
if (code.Length <= _codeLength)
throw new ProviderException(_errmsg9);
string parentCode = code.Substring(0, code.Length - 4);
// Make sure the parent code is valid
if (!_nodes.ContainsKey(parentCode))
throw new ProviderException(_errmsg4);
// Return the parent SiteMapNode
return _nodes[parentCode];
}
void OnSiteMapChanged(string key, object item, CacheItemRemovedReason reason)
{
lock (_lock)
{
if (key == _cacheDependencyName && reason == CacheItemRemovedReason.DependencyChanged)
{
// Refresh the site map
Clear();
_nodes.Clear();
_root = null;
}
}
}
/// <summary>
/// Clear Cached Site map tree.
/// </summary>
public void ClearSiteMap()
{
lock (_lock)
{
Clear();
_nodes.Clear();
_root = null;
}
}
}
}
以下是数据库脚本(MSSQL2000)
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap_Add]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SqlSiteMap_Add]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap_Del]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SqlSiteMap_Del]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap_Move]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SqlSiteMap_Move]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap_Query]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SqlSiteMap_Query]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap_QueryChildren]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SqlSiteMap_QueryChildren]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap_QueryParent]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SqlSiteMap_QueryParent]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap_QueryRoot]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SqlSiteMap_QueryRoot]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap_Reset]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SqlSiteMap_Reset]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap_ResetDataNum]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SqlSiteMap_ResetDataNum]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap_Select]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SqlSiteMap_Select]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap_SelectClassName]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SqlSiteMap_SelectClassName]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap_Update]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SqlSiteMap_Update]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap_UpdateDataNum]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SqlSiteMap_UpdateDataNum]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap_UpdateDataNumList]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[SqlSiteMap_UpdateDataNumList]
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[SqlSiteMap]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
drop table [dbo].[SqlSiteMap]
GO
CREATE TABLE [dbo].[SqlSiteMap] (
[ClassID] [int] NOT NULL ,
[ClassName] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[Code] [nvarchar] (200) COLLATE Chinese_PRC_CI_AS NOT NULL ,
[DataNum] [int] NULL ,
[Url] [nvarchar] (200) COLLATE Chinese_PRC_CI_AS NULL ,
[Roles] [nvarchar] (200) COLLATE Chinese_PRC_CI_AS NULL ,
[Target] [nvarchar] (50) COLLATE Chinese_PRC_CI_AS NULL ,
[Info] [nvarchar] (1000) COLLATE Chinese_PRC_CI_AS NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[SqlSiteMap] ADD
CONSTRAINT [DF_SqlSiteMap_DataNum] DEFAULT (0) FOR [DataNum],
CONSTRAINT [PK_SqlSiteMap] PRIMARY KEY CLUSTERED
(
[ClassID]
) ON [PRIMARY]
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
----添加分类存储过程
Create Proc SqlSiteMap_Add
@ClassName nvarchar(50),
@DataNum int ,
@Url nvarchar(200),@Roles nvarchar(200),@Target nvarchar(50),
@Info nvarchar(1000),
@ParentID int -- 0表示根类别
As
Declare @EditCode int
Declare @StepLen int
Declare @matchStr nvarchar(50)
Declare @typeCode nvarchar(50)
Declare @Code nvarchar(200)
Declare @MyCode nvarchar(200)
Declare @ParentCode nvarchar(200)
Declare @selfCode int
Set @editCode=1
Set @StepLen=4
Set @matchStr=REPLICATE('_',@StepLen) --4个_
set @typeCode=''
Set @Code=''
Set @MyCode=''
Set @selfCode=0
Set @ParentCode=''
Select @ParentCode=Code From [SqlSiteMap] Where ClassID=@ParentID
--//*
--判断当前分类编号是否有对应数据,当不允许在父类下添加数据时做下面的检测
--If Len(@ParentCode)>=@StepLen
--Begin
--If (Select Count(ArticleID) From [Article] Where ClassID=(Select ClassID From [ArticleClass] Where Code=@ParentCode) ) >0
--Begin
--RaisError ('父类下有数据,请将其数据转移后再添加',16,1)
--return
--End
--End
--*//
If(@editCode=1)
Begin
--获取子类中编号最大的Code,column.ParentCode + matchStr中
Select Top 1 @MyCode= Code From [SqlSiteMap] Where Code Like @ParentCode + @matchStr Order By Code DESC
If @@ROWCOUNT >0
Begin
Set @selfCode=Cast(Right(@MyCode,@StepLen) As Int ) +1
Set @typeCode=Replicate('0',@StepLen-1) + Cast(@selfCode As nvarchar)
Set @typeCode=Right(@typeCode,@StepLen)
Set @typeCode=@ParentCode + @TypeCode
End
Else
Begin
Set @typeCode=@ParentCode +Replicate('0',@StepLen-1)+'1'
End
End
Declare @ClassID int
Set @ClassID=0
--获取最大ClassID
Select @ClassId=Max(ClassID) From [SqlSiteMap]
If Not @ClassID Is Null
Begin
Set @ClassId=@ClassID +1
End
Else
Begin
Set @ClassID=1
End
Insert into [SqlSiteMap]
(ClassID,ClassName,Code,DataNum,[Url],[Roles],[Target], Info)
values
(@ClassID,@ClassName,@typeCode,@DataNum,@Url,@Roles,@Target, @Info)
Select @ClassID As ClassID
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
----删除一个分类,只允许删除没有字类的分类
Create Proc SqlSiteMap_Del
@ClassID int
As
If (Select Count(ClassID) From[SqlSiteMap] Where Code Like(Select Code From [SqlSiteMap] Where ClassID=@ClassID)+'%' And ClassId <> @ClassId ) >0
Begin
RaisError ('不能删除带有子类的分类',16,1)
Return
End
----当前分类下面是否有数据,因为前面判断了分类是最终叶分类,故这里直接用ClassID=@ClassID
--If (Select Count(ArticleID) From [Article] Where ClassId=@ClassID) >0
--Begin
--RaisError ('所删除的类别下有文章',16,1)
--Return
--End
Declare @Code nvarchar(200)
Declare @Value int
Set @Value=0
Select @Code=[Code],@Value=[DataNum] From [SqlSiteMap] Where [ClassID]=@ClassID
Update [SqlSiteMap] Set [DataNum]=[DataNum] - @Value Where [ClassID] In( Select ClassID From [SqlSiteMap] Where Len(Code)<=Len(@Code) And Code=Left(@Code,Len(Code)))
Delete From SqlSiteMap Where ClassID=@ClassID
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
---移动分类的排序
Create Proc SqlSiteMap_Move
@ClassID int,
@IsUp bit=1
As
Declare @maskStr nvarchar(200)
Declare @tempStr nvarchar(200)
Declare @Code nvarchar(200)
Set @Code=''
Set @tempStr=''
Select @Code=Code From [SqlSiteMap] Where ClassID=@ClassID
Set @maskStr=REPLICATE(N'-',Len(@Code))
If @Code !='' And ( (Len(@Code) % 4) =0 )
Begin
If(@isUp=1)
Begin
If(Len(@Code) > 4)
Begin
Select Top 1 @tempStr=Code From [SqlSiteMap] Where Len(Code)=Len(@Code) And Code < @Code And Left(Code,Len(Code)-4)=Left(@Code,Len(@Code)-4) Order By Code DESC
End
Else
Begin
Select Top 1 @tempStr=Code From [SqlSiteMap] Where Len(Code)=Len(@Code) And Code < @Code Order By Code DESC
End
End
Else
Begin
If(Len(@Code) >4)
Begin
Select Top 1 @tempStr=Code From [SqlSiteMap] Where Len(Code)=Len(@Code) And Code > @Code And Left(Code,Len(Code)-4)=Left(@Code,Len(@Code)-4) Order By Code ASC
End
Else
Begin
Select Top 1 @tempStr=Code From [SqlSiteMap] Where Len(Code)=Len(@Code) And Code >@Code Order By Code ASC
End
End
End
-- //已经是最前(最后)
If @tempStr Is Null Or RTrim(LTrim(@tempStr))=''
Begin
return
End
Declare @CodeLen int
Declare @MAXLEN int
Set @CodeLen=Len(@Code)
Set @MAXLEN=200
--//设置目标类,以及目标类的子类为----0001(目标类)或----00010002(子类)为形式
Update [SqlSiteMap] Set Code=@maskStr +Substring(code,@CodeLen +1,@MAXLEN) Where Left(code,@CodeLen)=@tempStr
--//更新当前交换类(包括子类)Code为目标类Code
Update [SqlSiteMap] Set Code=@tempStr +Substring(Code,@CodeLen+1,@MAXLEN) Where Left(code,@CodeLen)=@Code
--//更新目标类(包括子类)Code为当前交换类Code
Update [SqlSiteMap] Set Code=@Code +Substring(code,@CodeLen +1,@MAXLEN) Where Left(code,@CodeLen)=@maskStr
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
----获取整个分类信息
CREATE Proc SqlSiteMap_Query
As
Select [ClassID],[ClassName],[Code],[Url],[Roles],[Target], [DataNum],[Info] From [SqlSiteMap] Order By [Code]
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
----获取指定类的子类,并包括自身
Create Proc SqlSiteMap_QueryChildren
@ClassID int
As
Declare @Code nvarchar(200)
Select @Code=[Code] From [SqlSiteMap] Where [ClassID]=@ClassID
Select [ClassID],[ClassName],[Code],[Url],[Roles],[Target], [DataNum]
From [SqlSiteMap] Where Code Like @Code +'%' Order By Code
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
-----获取指定分类的父分类信息
Create Proc SqlSiteMap_QueryParent
@ClassID int
As
Declare @ClassCode nvarchar(200)
Select @ClassCode=Code From [SqlSiteMap] Where ClassId=@ClassID
Select ClassID,ClassName,Code,[Url],[Roles],[Target], DataNum
From [SqlSiteMap]
Where Len(Code)<=Len(@ClassCode)
And Code = Left(@ClassCode,Len(Code))
Order By Code
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
-----获取顶级分类列表
Create Proc SqlSiteMap_QueryRoot
AS
Select [ClassID],[ClassName],[Code],[Url],[Roles],[Target], [DataNum] From [SqlSiteMap] Where Len(Code)=4 Order By Code
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
-------重置所有分类为根分类
Create Proc SqlSiteMap_Reset
As
Declare @code nvarchar(200)
Declare @i int
Set @Code=''
Set @i=1
----修改DataNum列
Declare @Total int
Declare SqlSiteMap_Cursor_Order Cursor For
Select Code From [SqlSiteMap] Order By Code
Open SqlSiteMap_Cursor_Order
Fetch Next From SqlSiteMap_Cursor_Order
Into @Code
WHile @@FETCH_STATUS=0
Begin
Select @Total= Sum(DataNum) From [SqlSiteMap] Where Code Like @Code + Replicate('_',4)
If Not( @Total Is Null)
Begin
Update [SqlSiteMap] Set DataNum=DataNum - @Total WHERE Current Of SqlSiteMap_Cursor_Order
End
Set @Total=0
Fetch Next From SqlSiteMap_Cursor_Order Into @Code
End
Close SqlSiteMap_Cursor_Order
DEALLOCATE SqlSiteMap_Cursor_Order
Declare SqlSiteMap_Cursor CURSOR For
Select CODE From [SqlSiteMap]
Open SqlSiteMap_Cursor
Fetch Next From SqlSiteMap_Cursor
WHILE @@FETCH_STATUS=0
Begin
Set @Code=Replicate(N'0',4) + Cast(@i as nvarchar)
Set @Code=Right(@Code,4)
Update [SqlSiteMap] Set Code= @Code WHERE Current Of SqlSiteMap_Cursor
Set @i=@i+1
Fetch Next From SqlSiteMap_Cursor
End
Close SqlSiteMap_Cursor
DEALLOCATE SqlSiteMap_Cursor
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
Create Proc SqlSiteMap_ResetDataNum
@ClassID int
As
Declare @Code nvarchar(200)
Declare @Value int
Set @Value=1
Select @Code=[Code],@Value=[DataNum] From [SqlSiteMap] Where ClassID=@ClassID
Update [SqlSiteMap] Set [DataNum]=[DataNum] - @Value Where [ClassID] In( Select ClassID From [SqlSiteMap] Where Len(Code)<=Len(@Code) And Code=Left(@Code,Len(Code)))
Update [SqlSiteMap] Set [DataNum]=0 Where [Code] Like @Code + '%'
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
----选择存储过程
Create PROCEDURE SqlSiteMap_Select
@ClassID int
AS
SELECT [ClassID],[ClassName],[Code],[DataNum],[Url],[Roles],[Target], [Info]
FROM [SqlSiteMap]
WHERE
[ClassID]=@ClassID
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
----获取指定分类的分类名称
Create Proc SqlSiteMap_SelectClassName
@ClassID int
AS
Select [ClassName] From [SqlSiteMap] Where [ClassID]=@ClassID
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
----修改分类存储过程
Create Proc SqlSiteMap_Update
@ClassID int , --需要修改的ClassID
@ClassName nvarchar(50),
@Url nvarchar(200),@Roles nvarchar(200),@Target nvarchar(50),
@Info nvarchar(1000),
@ParentID int
As
Declare @EditCode int
Declare @StepLen int
Declare @matchStr nvarchar(50)
Declare @typeCode nvarchar(50)
Declare @Code nvarchar(200)
Declare @MyCode nvarchar(200)
Declare @ParentCode nvarchar(200)
Declare @selfCode int
Set @editCode=0
Set @StepLen=4
Set @matchStr=REPLICATE('_',@StepLen) --4个_
set @typeCode=''
Set @Code=''
Set @MyCode=''
Set @selfCode=0
Set @ParentCode=''
Select @ParentCode=Code From [SqlSiteMap] Where ClassID=@ParentID
Select @Code=Code From [SqlSiteMap] Where ClassID=@ClassID
--//*
--判断当前分类编号是否有对应数据,当不允许在父类下添加数据时做下面的检测
--If Len(@ParentCode)>=@StepLen
--Begin
--If (Select Count(ArticleID) From [Article] Where ClassID=(Select ClassID From [ArticleClass] Where Code=@ParentCode) ) >0
--Begin
--RaisError ('父类下有数据,请将其数据转移后再添加',16,1)
--return
--End
--End
--*//
--修改原有类别
--确定是否要修改Code字段
--查看是否改变了直接父类别(上一级)
If @ParentCode != Left(@code,len(@code)-@StepLen)
Begin
--过滤选择自己做为父类
If(@ParentCode !=@Code)
Begin
--过滤选择自己的子类为父类
If Len(@ParentCode) > Len(@Code)
Begin
--因为 Len(@ParentCode) > Len(@Code) 所以可以Left(@ParentCode,Len(@Code))
If Left(@ParentCode,Len(@Code)) != @Code --如果相等则为选择自己的子类为父类
Begin
Set @EditCode=1
End
End
Else
Begin
Set @EditCode=1
End
End
End
If(@editCode=1)
Begin
--获取子类中编号最大的Code,column.ParentCode + matchStr中
Select Top 1 @MyCode= Code From [SqlSiteMap] Where Code Like @ParentCode + @matchStr Order By Code DESC
--是否有子类
If @@ROWCOUNT >0
Begin
Set @selfCode=Cast(Right(@MyCode,@StepLen) As Int ) +1
Set @typeCode=Replicate('0',@StepLen-1) + Cast(@selfCode As nvarchar)
Set @typeCode=Right(@typeCode,@StepLen)
Set @typeCode=@ParentCode + @TypeCode
End
Else --没有子类那么编号从1开始
Begin
Set @typeCode=@ParentCode +Replicate('0',@StepLen-1)+'1'
End
End
If (@editCode=1)
Begin
Update [SqlSiteMap] Set
ClassName=@ClassName,Code=@typeCode,[Url]=@Url,[Roles]=@Roles,[Target]=@Target, Info=@Info
where ClassID=@ClassID
End
Else
Begin
Update [SqlSiteMap] Set
ClassName=@ClassName,[Url]=@Url,[Roles]=@Roles,[Target]=@Target, Info=@Info
where ClassID=@ClassID
End
---修改子类编号(Code)
If(@editCode=1)
Begin
Update [SqlSiteMap] Set
Code=@typeCode + Right(Code,Len(Code)-Len(@Code))
Where Code Like @Code + '%'
End
----修改DataNum列
Declare @Value int
Set @Value=0
If(@editCode=1)
Begin
Select @Value=[DataNum] From [SqlSiteMap] Where ClassID =@ClassID
--原有的父类递归减少指定数目
Update [SqlSiteMap] Set [DataNum]=[DataNum] - @Value Where [ClassID] In( Select ClassID From [SqlSiteMap] Where Len(Code)<Len(@Code) And Code=Left(@Code,Len(Code)))
--现在的父类递归增加指定数目
Update [SqlSiteMap] Set [DataNum]=[DataNum] + @Value Where [ClassID] In( Select ClassID From [SqlSiteMap] Where Len(Code)<Len(@TypeCode) And Code=Left(@TypeCode,Len(Code)))
End
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
-------更新DataNum列
Create Proc SqlSiteMap_UpdateDataNum
@ClassID int,
@IsIncrease bit=1, --增加或减少
@Value int =1
As
Declare @Code nvarchar(200)
Select @Code=[Code] From [SqlSiteMap] Where [ClassID]=@ClassID
If @IsIncrease=1
Begin
Update [SqlSiteMap] Set [DataNum]=[DataNum] + @Value Where [ClassID] In( Select ClassID From [SqlSiteMap] Where Len(Code)<=Len(@Code) And Code=Left(@Code,Len(Code)))
End
Else
Begin
Update [SqlSiteMap] Set [DataNum]=[DataNum] - @Value Where [ClassID] In( Select ClassID From [SqlSiteMap] Where Len(Code)<=Len(@Code) And Code=Left(@Code,Len(Code)))
End
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_NULLS ON
GO
----批量更新列的DataNum值,@IDs输入的形式为: '1,2,234,2345,22'
Create Proc SqlSiteMap_UpdateDataNumList
@IDs nvarchar(2000),
@IsIncrease bit=1, --增加或减少
@Value int=1
As
If @IDs=''
Begin
return
End
Declare @ClassID int
Declare @Code nvarchar(200)
Declare @s int
Declare @Len int
Declare @DataLen int
Set @Len=0
Set @s=1
Set @IDs=','+@IDs+',' --变成 ',1,334,23,'这样的形式
Set @DataLen=Len(@IDs)
While @s<@DataLen
Begin
Set @s=@s+1
Set @Len=CharIndex(',',@IDs,@s)-@s
Set @ClassID=Cast(Substring(@IDs,@s,@Len) as int)
---更新操作
Select @Code=[Code] From [SqlSiteMap] Where [ClassID]=@ClassID
If @IsIncrease=1
Begin
Update [SqlSiteMap] Set [DataNum]=[DataNum] + @Value Where [ClassID] In( Select ClassID From [SqlSiteMap] Where Len(Code)<=Len(@Code) And Code=Left(@Code,Len(Code)))
End
Else
Begin
Update [SqlSiteMap] Set [DataNum]=[DataNum] - @Value Where [ClassID] In( Select ClassID From [SqlSiteMap] Where Len(Code)<=Len(@Code) And Code=Left(@Code,Len(Code)))
End
----更新操作结束
Set @s=@s+@Len
End
GO
SET QUOTED_IDENTIFIER OFF
GO
SET ANSI_NULLS ON
GO
以下是web.config配置,需同时配置角色,用户等提供程序
<siteMap enabled="true" defaultProvider="AspNetSqlSiteMapProvider">
<providers>
<add name="AspNetSqlSiteMapProvider" type="FStudio.Provider.SqlSiteMapProvider,FStudio.Provider" securityTrimmingEnabled="true" connectionStringName="MainDB"/>
</providers>
</siteMap>
<authentication mode="Forms">
<forms loginUrl="/log.aspx" defaultUrl="~/user/UserTrade.aspx" timeout="120"/>
</authentication>
<roleManager defaultProvider="SqlProvider" enabled="true" cacheRolesInCookie="true" cookieName=".WOW52.COOKIENAME" cookieTimeout="120" cookieRequireSSL="false" cookieSlidingExpiration="true" createPersistentCookie="true" cookieProtection="All">
<providers>
<add name="SqlProvider" type="System.Web.Security.SqlRoleProvider" connectionStringName="MainDB" applicationName="WOW52.CN"/>
</providers>
</roleManager>
<membership defaultProvider="SqlProvider">
<providers>
<add name="SqlProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="MainDB" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" passwordFormat="Hashed" minRequiredNonalphanumericCharacters="0" minRequiredPasswordLength="6" requiresUniqueEmail="false" applicationName="WOW52.CN"/>
</providers>
</membership>