杂志网站的数据库设计,具有灵活的水平菜单



我需要设计一个基于CMS的网站 asp.net 使用网络表单(c#)和MS SQL Server作为杂志网站的后端数据库,该网站将每周发行一期。

示例数据

MagazinePages Table
PageID  PageName    LangID  PagePositionNo  PageURL     PageInheritance //PageID 
1           Home        1         10        Default.aspx    0
2           About Us    1         20        Page.aspx       0
3           PageOne     1         10        Page.aspx       2
4           PageTwo     1         20        Page.aspx       2
5           Media           1         30        Page.aspx       0
6           Video       1         10        Videos.aspx     5
8           News        1         40        News.aspx        0
9           Archive     1         50        #               0
10          Publication 1         60        Page.aspx       0
11          SpanishHome 2         10        Default.aspx        0
12          SpanisAboutUs 2       20        Page.aspx   0
------------------------------------------------------------------------------
Magazine
MagazineID  MagazineIssueCode   LangID  MagazineTitle   MagazineLiveIssue(CurrentIssue)
1       1           1   Mag Title       0
2       2           1   Mag Title       1
3       1           2   SpanisgMag Title    0
4       2           2   Mag Title       1
------------------------------------------------------------------------------
News Table
NewsID  NewsTitle   NewsCatID   MagazineID  Language    
1   News one    100     1       1
2   News two    100     1       1
3   news three  200     1       1
4   News four   300     1       1
5   News Five   100     2       1
6   News Six    300     2       1
7   News seven  200     2       2
------------------------------------------------------------------------------

上述方法的问题在于,只有当所有记录都在基于上述示例的MagazinePages中时,我才能创建子菜单,我可以为"关于我们"和多媒体创建子菜单如何设计我的数据库,以便我可以从不同的表中提取数据,例如按类别(政治、文化......)和杂志表中的问题(第 101 期,问题 102, 问题 103....)

我计划为此使用 ASP 菜单控件,这可能不是很灵活,因为我将有超过 100 期杂志如何或哪些多列菜单我可以与 asp.net 一起使用

我的数据库可能有很多流程,我将不胜感激这方面的帮助,以便我可以将此数据库用于此CMS系统。请随时提出有关此的问题。

新增: 如果我需要从MagazinePages表中提取所有菜单名称,那么这很容易,但我已经被要求有一个菜单结构,如示例中所示。问题是我可以从MagazinePages表中生成AboutUsMultimedia菜单,但我没有任何页面,如政治,经济,...问题 101、102、103..在此表中,因为该信息存储在不同的表中,例如News CategoryMagazine表中的新闻表和问题。 我宁愿改变我的表格设计并使其灵活地从单独的表格中读取菜单信息,但我不确定如何

新闻表不在此架构中显示。

我所做的是我已经为CMS页面创建了ps_Pages表,例如主页,关于我们,联系人,媒体中心.....

我将与杂志相关的页面(实际上是具有不同类别或标签的文章,如文化,政治,体育,人物art_Article......

为什么不让一个页面来处理内容?

只需致电Page.aspx?Issue=4&Page=4

然后在你的代码中,你知道这是第 4 期,他们想要第 4 页,然后你可以在 Page.aspx(.vb 或 .cs)中有代码来翻译它,然后决定布局。

所以例如

Page.aspx?Issue=4&Style=Article&Content=5

因此,在代码中,您可以转到,好吧,这是问题 4 获取问题 4 的数据库条目,好吧,他们想要问题 4 中的 Content ID 5,然后放入文章的样式。

这意味着您不必在数据库类型中添加额外的页面,您可以根据需要添加内容,并且生成URL以访问内容的项目只需要显示所有内容。

我认为您需要重新评估数据库架构。 例如,我会有一个名为"ParentMenuItems"的表。

此表将包括所有热门菜单项(主页、关于我们、问题等),并包含子菜单的文本。 然后,您需要有一个与您的父菜单项有关系的 ChildMenu 表。

ParentMenuItems:
==============================================================
ID       | LinkText      | LangID     | Other Properties
==============================================================
1        | Home.aspx     | 1          | blah blah blah
2        | AboutUs.aspx  | 2          | blah blah blah

然后,你可以有另一个名为"ChildMenuItems"的表,如下所示:

ChildMenuItems:
===============================================================
ID   | LinkText       | LangID |  ParentID  | Other Properties...
===============================================================
1    | PageOne.aspx   | 1      | 2          | blah blah blah
2    | PageTwo.aspx   | 2      | 2          | blah blah blah

代码可以像这样工作:

SELECT * FROM ParentMenuItems - //SQL to get Items

然后,编写一些 foreach 代码来枚举 SQL 结果

foreach(var ParentMenuItem in ParentMenuItems)
{ 
//Get ParentMenuItem ID, run SQL select on child menu items, Example:
//SELECT * from ChildMenuItems where ParentID = ID.FROM.PARENT.RESULT
// Now you have all the child menu items, foreach those and add to repeater control
}

我希望这有所帮助。 如果您有任何疑问,请告诉我。

提示:实体框架将对此进行非常轻松的工作。

我不确定我是否理解您的需求,但我假设您要为整个系统创建一个菜单,而不是为每个杂志创建一个菜单,对吗?

如果是这样,我认为您正在寻找错误的问题:问题不在于数据库模式,而在于您的菜单应该由 N 个没有预定义标准的不同表自动填充的概念。

我会创建一个菜单表 - 并使杂志页面和菜单成为两个不同的表:如果您正在创建一个类似CMS的系统,您可能会有一个页面,我可以在其中编辑类别,问题和 - 为什么不 - 菜单条目,完全独立于任何其他表。

此外,我会创建一个"标签"系统,我所有的新闻和问题都可以被"标记",而不是放在一个独家类别中。它有可能同时谈论政治和文化的新闻。然后,与其将用户定向到许多不同的页面.aspx,不如使用content.aspx?tag=politics。创建标签时,我可以选择将此标签添加到菜单表的"新闻"、"问题"等下。类别和问题相同。

如果它不符合您的需求,您可以尝试这些选项 - 但除了菜单项的特定表之外,所有其他解决方案都会在我的大脑中搜索"警告,检测到未来问题":

1 - 创建一个菜单表,一个通过遵循特定规则填充此表的存储过程,然后在诸如"类别"之类的表上触发,这些表将截断并调用存储过程,每次内容更改时重写菜单(听起来对我来说是一个快速修复)

2 - 在杂志页面中添加"submenu_table","submenu_field","submenu_condition"等,并使用动态SQL选择数据(类似于Set @SQL='Select '+ submenu_field + ' from '+ submenu_table + ' where ' + submenu_condition; Exec(@SQL))(另一个快速修复,繁重且可能很慢的查询)

(编辑:) 3 - SQL 2008 及更高版本中还有 hierachyId 字段 ([http://blogs.msdn.com/b/manisblog/archive/2007/08/17/sql-server-2008-hierarchyid.aspx])1

为菜单的

CREATE TABLE [dbo].[tblMenuMaster](
[MenuID] [int] IDENTITY(1,1) NOT NULL,
[MenuName] [varchar](100) NULL,
[DisplayOrder] [int] NULL,
PRIMARY KEY CLUSTERED 
(
[MenuID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

为子菜单创建另一个表

CREATE TABLE [dbo].[tblSubMenuMaster](
[SubMenuID] [int] IDENTITY(1,1) NOT NULL,
[MenuID] [int] NULL,
[SubMenuName] [varchar](100) NULL,
[MainMenuDisplayOrder] [int] NULL,
[DisplayOrder] [int] NULL,
[SubMenuUrl] [varchar](500) NULL,
[VisibleInMenu] [bit] NULL,
PRIMARY KEY CLUSTERED 
(
[SubMenuID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]
GO

现在转到母版页.. HTML 代码是:

<div class="menubar">
<%--<ul class="tabs">--%>
<asp:Literal ID="ltMenus" runat="server"></asp:Literal>
<%--</ul>--%>
</div>

代码背后的代码是:

private void GenerateMenus()
{
clsMenu obj = new clsMenu();
System.Data.DataSet ds = new System.Data.DataSet();
String PageName = "";
PageName = Path.GetFileName(Page.AppRelativeVirtualPath);
ds = obj.GetMenusByRole(GetRoleId(), PageName);
StringBuilder sb = new StringBuilder("<ul class='tabs'>");
foreach (System.Data.DataRow row in ds.Tables[0].Rows)
{
sb.Append(String.Format("<li class='{0}'><a rel='{1}' href='{1}' > {2} </a> ", Convert.ToString(row["css"]), ResolveUrl(Convert.ToString(row["PagePath"])), Convert.ToString(row["MenuName"])));
//sb.Append(String.Format("<li '><a rel='{0}' href='{0}' > {1} </a> ", ResolveUrl(Convert.ToString(row["PagePath"])), Convert.ToString(row["MenuName"])));
System.Data.DataTable t = CCMMUtility.GetFilterDataforIntColumn("MenuID", Convert.ToString(row["MenuID"]), ds.Tables[1]);
if (t.Rows.Count > 0)
{
sb.Append("<ul>");
for (int i = 0; i < t.Rows.Count; i++)
{
sb.Append(String.Format("<li><a href='{0}' class='dir' style='cursor: pointer;'>{1}</a></li>", ResolveUrl(Convert.ToString(t.Rows[i]["PagePath"])), Convert.ToString(t.Rows[i]["PageAliasName"])));
}
sb.Append("</ul>");
}
sb.Append("</li>");
}
sb.Append("</ul>");

ltMenus.Text = sb.ToString();
}

它需要存储的过程才能根据角色 ID 调用菜单的动态,如下所示

CREATE PROCEDURE [dbo].[proc_GetMenusByRole]
(
@RoleId int,  
@PageName varchar(100)
)
AS
SET NOCOUNT ON;
SELECT mm.MenuID, mm.MenuName,dbo.Extract_CssNameForMenuByMenuIDAndPageName(mm.MenuID, @PageName) as css
,dbo.proc_Extract_MenuPageByRoleIDAndMenuID(@RoleId, mm.MenuID)
as PagePath , mm.DisplayOrder   FROM tblMenuMaster mm WHERE mm.MenuID IN (SELECT s.MenuID from tblSiteRolePermissions p INNER JOIN
tblSitePages s ON p.fkSitePageId = s.pkSitePageId
WHERE (p.fkRoleId = @RoleId and p.ViewOnly=1))   
Union All   
select 0 as menuid ,'Change Password' as MenuName,  
case @pagename   
when 'ChangePassword.aspx' then 'active'  
else ''  
end  as css,'~/User/ChangePassword.aspx' as PagePath, 10000 as Displayorder  
ORDER BY DisplayOrder     
SELECT s.MenuID, s.pkSitePageId, s.PageAliasName, s.SitePageName,s.pagepath from tblSiteRolePermissions p 
INNER JOIN tblSitePages s ON p.fkSitePageId = s.pkSitePageId  WHERE (p.fkRoleId =@RoleId and p.ViewOnly=1) ORDER BY s.pkSitePageId  

新 sp 从这里开始

CREATE function [dbo].[Extract_CssNameForMenuByMenuIDAndPageName](@MenuID int, 
PageName varchar(100))
returns nvarchar(50)
as begin      
declare @result nvarchar(50) 
set @result = ''    
IF EXISTS (SELECT pkSitePageId FROM tblsitepages WHERE (MenuID = @MenuID) AND (UPPER(SitePageName) = @PageName)) 
BEGIN    
SET @result = 'active'    
END    
return @result    
end  

使用的另一个 sp 是

CREATE function [dbo].[proc_Extract_MenuPageByRoleIDAndMenuID]
(@RoleId int, @MenuID int)
returns nvarchar(500) 
as begin          
declare @result nvarchar(500)
SELECT top 1 @result = s.pagepath FROM tblSitePages AS s INNER JOIN tblSiteRolePermissions AS p ON s.pkSitePageId = p.fkSitePageId
WHERE (p.fkRoleId = @RoleId) AND (s.MenuID = @MenuID)  and p.ViewOnly=1
ORDER BY s.pkSitePageId 
return  @result
end  

这只是一种方法,您可以根据需要对其进行修改......

proc_Extract_MenuPageByRoleIDAndMenuIDsp 用于获取页面名称及其路径,

Extract_CssNameForMenuByMenuIDAndPageNamesp 用于将活动类设置为第一个li表示第一个菜单。 跳这个会帮助你..... 它的工作代码..

相关内容

  • 没有找到相关文章

最新更新