代码改变世界

LINQ TO SQL学习笔记(7)_递归实现TreeView导航

2009-06-16 16:55  宗哥  阅读(2758)  评论(8编辑  收藏  举报

LINQ TO SQL学习笔记(7)_递归实现TreeView导航

引言

本文介绍Linq to sql在实际工程中的例子,利用TreeView,递归实现导航功能。在下一篇当中我们会结合角色权限进行有选择的加载。

系统环境

  1. Visual Studio 2010 +NET Framework 3.5+Microsoft SQL Server 2005+Window XP+ SP3
  2. LINQ TO SQL采用配置式开发

开发实现

    由于linq to sql属于ORM属于Bottom Up的ORM设计框架,结合TreeView特点。我们先设计数据库。

  1. 数据库设计观察TreeView的Node的特点,一种是有子点,另外一种是叶子节点。我们设计的PDM模型如下:
    1. 有子点的Node对象对应模块分类表,叶子节点Node对应模块表。其中模块分类表自身有1对多关系(一个模块分类可以继续子分类),和模块表是1对多关系(对各叶子节点模块属于同一个模块分类)
    2. 生成表PB_MODULE_TYPE 的SQL(MS SQLSERVER 2005)如下:
      USE [Test]
      GO
      /****** 对象:  Table [dbo].[MODULE_TYPE]    脚本日期: 06/16/2009 17:05:43 ******/
      SET ANSI_NULLS ON
      GO
      SET QUOTED_IDENTIFIER ON
      GO
      SET ANSI_PADDING ON
      GO
      CREATE TABLE [dbo].[MODULE_TYPE](
          
      [ID] [varchar](15) COLLATE Chinese_PRC_CI_AS NOT NULL,
          
      [PARENT_ID] [varchar](15) COLLATE Chinese_PRC_CI_AS NULL,
          
      [NAME] [varchar](40) COLLATE Chinese_PRC_CI_AS NOT NULL,
          
      [REMARK] [varchar](200) COLLATE Chinese_PRC_CI_AS NULL,
          
      [ORDER_ID] [int] NOT NULL,
       
      CONSTRAINT [PK_PB_MODULE_TYPE] PRIMARY KEY NONCLUSTERED 
      (
          
      [ID] ASC
      )
      WITH (IGNORE_DUP_KEY = OFFON [PRIMARY]
      ON [PRIMARY]

      GO
      SET ANSI_PADDING OFF
      GO
      USE [Test]
      GO
      ALTER TABLE [dbo].[MODULE_TYPE]  WITH CHECK ADD  CONSTRAINT [FK_PB_MODULE_TYPE_PB_MODULE_TYPE] FOREIGN KEY([PARENT_ID])
      REFERENCES [dbo].[MODULE_TYPE] ([ID])

      INSERT INTO dbo.PB_MODULE_TYPE (PB_ID,  PB_NAME, PB_ORDER_ID) VALUES ('0000000001''分类1'10
      INSERT INTO dbo.PB_MODULE_TYPE (PB_ID, PB_PARENT_ID ,PB_NAME, PB_ORDER_ID) VALUES ('0000000011','0000000001''分类11',11
      INSERT INTO dbo.PB_MODULE_TYPE (PB_ID, PB_PARENT_ID ,PB_NAME, PB_ORDER_ID) VALUES('0000000012''0000000001','分类12'12
      INSERT INTO dbo.PB_MODULE_TYPE (PB_ID, PB_NAME,PB_ORDER_ID) VALUES ('0000000002''分类2'20
      INSERT INTO dbo.PB_MODULE_TYPE (PB_ID, PB_NAME, PB_ORDER_ID) VALUES ('0000000003''分类3'30
      INSERT INTO dbo.PB_MODULE_TYPE (PB_ID, PB_NAME, PB_ORDER_ID) VALUES ('0000000004''分类4'40
      go 
    3. 生成表PB_MODULE_TYPE 的SQL(MS SQLSERVER 2005)如下:
      USE [Test]
      GO
      /****** 对象:  Table [dbo].[MODULE]    脚本日期: 06/16/2009 17:06:41 ******/
      SET ANSI_NULLS ON
      GO
      SET QUOTED_IDENTIFIER ON
      GO
      SET ANSI_PADDING ON
      GO
      CREATE TABLE [dbo].[MODULE](
          
      [ID] [varchar](15) COLLATE Chinese_PRC_CI_AS NOT NULL,
          
      [MODULE_TYPE_ID] [varchar](15) COLLATE Chinese_PRC_CI_AS NOT NULL,
          
      [TAG] [varchar](40) COLLATE Chinese_PRC_CI_AS NOT NULL,
          
      [NAME] [varchar](40) COLLATE Chinese_PRC_CI_AS NOT NULL,
          
      [MODULE_URL] [varchar](200) COLLATE Chinese_PRC_CI_AS NULL,
          
      [REMARK] [varchar](200) COLLATE Chinese_PRC_CI_AS NULL,
          
      [DISABLED] [int] NOT NULL,
          
      [ORDER_ID] [int] NOT NULL,
       
      CONSTRAINT [PK_PB_MODULE] PRIMARY KEY NONCLUSTERED 
      (
          
      [ID] ASC
      )
      WITH (IGNORE_DUP_KEY = OFFON [PRIMARY]
      ON [PRIMARY]

      GO
      SET ANSI_PADDING OFF
      GO
      USE [Test]
      GO
      ALTER TABLE [dbo].[MODULE]  WITH CHECK ADD  CONSTRAINT [FK_PB_MODULE_PB_MODULE_TYPE1] FOREIGN KEY([MODULE_TYPE_ID])
      REFERENCES [dbo].[MODULE_TYPE] ([ID])
      INSERT INTO dbo.PB_MODULE (PB_ID, PB_MODULE_TYPE_ID, PB_TAG, PB_NAME, PB_MODULE_URL, PB_DISABLED, PB_ORDER_ID) VALUES ('0000000000''0000000001''SysCodeMgr''百度''www.ambow.com'010)
      INSERT INTO dbo.PB_MODULE (PB_ID, PB_MODULE_TYPE_ID, PB_TAG, PB_NAME, PB_MODULE_URL, PB_DISABLED, PB_ORDER_ID) VALUES ('0000000001''0000000001''ModuleMgr''安博''www.ambow.com'020)
      INSERT INTO dbo.PB_MODULE (PB_ID, PB_MODULE_TYPE_ID, PB_TAG, PB_NAME, PB_MODULE_URL, PB_DISABLED, PB_ORDER_ID) VALUES ('0000000002''0000000011''RoleMgr''软件培训''www.ambow.com'010)
      INSERT INTO dbo.PB_MODULE (PB_ID, PB_MODULE_TYPE_ID, PB_TAG, PB_NAME, PB_MODULE_URL, PB_DISABLED, PB_ORDER_ID) VALUES ('0000000003''0000000012''DepartmentMgr''心心相映'''020)
      INSERT INTO dbo.PB_MODULE (PB_ID, PB_MODULE_TYPE_ID, PB_TAG, PB_NAME, PB_MODULE_URL, PB_DISABLED, PB_ORDER_ID) VALUES ('0000000004''0000000012''StaffMgr''昆山安博软件外包产业园''www.ambow.com'030)
      INSERT INTO dbo.PB_MODULE (PB_ID, PB_MODULE_TYPE_ID, PB_TAG, PB_NAME, PB_MODULE_URL, PB_DISABLED, PB_ORDER_ID) VALUES ('0000000005''0000000002''ChangeMyPwd''新浪''www.sina.com'010)
      INSERT INTO dbo.PB_MODULE (PB_ID, PB_MODULE_TYPE_ID, PB_TAG, PB_NAME, PB_MODULE_URL, PB_DISABLED, PB_ORDER_ID) VALUES ('0000000006''0000000003''UserMgr''雅虎''www.qq.com'010)
  2. 代码实现
    1. 采用配置的方式进行Linq to SQL开发,生成DBML,命令如下 sqlMetal /conn:server=172.1.42.15;database=ZXKP;uid=sa;pwd=1 /DBML:D:\ZXKP.dbml /namespace:DMN /serialization:Unidirectional ,把生成的DBML文件加到你的工程中,生成的类图如下:

      对于采用敏捷方法开发的,数据库可能经常微调,对于sqlMetal工具,我们可以让输出路径就是你的工程中的dbml文件路径。另外sqlMetal对于输出提供的可控制性太少,实体类属性和你数据库字段设计的一样,所以你在设计数据库时候尽量编码符合C#规范些。

    2. 递归实现代码,首先找个Potal,加载根节点:
           private void LoadModuleTree()
              {
                  
      //获取所有顶层模块。
                  DMN.ZXKP  context = new  DMN.ZXKP();
                  
                  
      //未审核的状态
                  var topModuleType = from m in context.MODULE_TYPE
                               
      where m.PARENT_ == null
                               select m;
                           
                 TreeNode TopNode 
      = new TreeNode("功能模块");
                  
                  
      //增加模块分类和模块。
                 foreach (MODULE_TYPE mt in topModuleType)
                  {
                      TreeNode node 
      = new TreeNode();
                      TopNode.ChildNodes.Add(node);
                      node.Text 
      = mt.NAME;

                      node.ToolTip 
      = mt.NAME;

                      AddSubNodes(node, mt);
                      node.Expanded 
      = false;

                  }

                 tvMenu.Nodes.Add(TopNode);

              }
      递归加载其余节点:
          private void AddSubNodes(TreeNode currentNode, MODULE_TYPE currentModuleType)
              {


                  
      //增加子模块分类
                  foreach (MODULE_TYPE mt in currentModuleType.MODULE_TYPE_MODULE_TYPE)
                  {
                      TreeNode subNode 
      = new TreeNode();
                      currentNode.ChildNodes.Add(subNode);

                      subNode.Text 
      = mt.NAME;

                      subNode.ToolTip 
      = mt.NAME;

                      AddSubNodes(subNode, mt);

                  }

                  
      //增加模块
                  foreach (MODULE m in currentModuleType.MODULE)
                  {
                      TreeNode nodeModule 
      = new TreeNode();
                      currentNode.ChildNodes.Add(nodeModule);

                      nodeModule.Text 
      = m.NAME;

                      nodeModule.ToolTip 
      = m.NAME;
                      nodeModule.NavigateUrl 
      = m.MODULE_URL;

                  }
              }
    3. 实现效果图:

代码下载

  1. 采用Studion 2010开发。
    1. 源代码: /Files/Roping/Linq2SQL.rar
    2. 数据库: /Files/Roping/test.rar
;