背景:

最近给客户做了一个小工具,主要是为了减轻客户那边的工作压力,一般公司都有很多自己的业务数据需要定期发给自己的员工,比如各种指标数据,绩效评比等, 大多都是按公司的组织结构来,一级一级往下发,领导接收的数据一般会包含自己下一级人员的数据,所以客户这边也不例外,每次到了一定的周期(每周,每月或者每季度),就会由专业人员将一份完整的数据分别按组织结构一级一级往下发,全体领导基本都需要做这件事。
     
      于时,我们需要给领导做一个自动分发数据的工具,将这些数据按一定要求自动的发送到各自人的邮箱中,需求给简单,就是发邮件,从程序功能上讲也就分三部分:
      1:解析数据源并加载到数据库中
      2:提取数据并发送邮件
      3:将发送结果反馈给指定的人
     
      之前我们一致认为数据源是稳定的,数据源格式是excel,里面的sheet名称及数量是固定的,字段也是固定的(字段数量以及名称),所以我们有一种非常简单的做法,就是将excel的每个sheet映射成数据库中的一张表,表字段和excel字段一一对应即可,最后根据不同的业务数据需求,构建不同的邮件模块,最后实现邮件发送。
     
      问题:
      但有一天,我们的客户负责人发生了变更,他提出了一个问题:如果以后发送的数据发生变化,你们的软件能支持吗,比如今年我们的excel发送的是10个指标数据,明年如果想再增加5个或者重新替换原来的指标。
     
      由于我们对此工具的定位非常低,及不用花太大代价在小工具上,尽早用上尽早减轻客户工作量,同时也会降低开发成本,当时我们理解为数据源不会轻易发生变化,所以设计了上面的解决方案,及不支持数据的动态变更。但新的负责人提出了我们的方案不够灵活,可扩展性,可配置性稍弱,为此我们不得不重新设计方案以支持指标数据的动态变化需求,哎,怎么说呢,如果我们给客户想的多想的全,他们也有可能说,就一小工具不用这么复杂吧,总之既然问题提出我们就需要想办法及解决呀。
     
      习惯性思维产生的解决方案:
      动态构建数据表,及首先解析每个sheet有多少列,然后将这些列信息映射为数据库表,这个方案有如下缺点:
      缺点一:sheet的列名需要特殊处理才行,我们需要在前面增加 []标识,以防止字符不符合表字段要求;
      缺点二:理论上数据库表的列最大数没有excel的大,即在某种极端的情况下,无法容纳所有excel列数据;
      缺点三:在数据库查询上不方便,因为字段都是未知的;
      缺点四:在绑定email模板(email模板是用xlst来做的)上也是个问题,同样也是字段都是未知的;
      缺点五:每次导入数据都需要全部删除数据库中的表,然后重建,这会带来一些不可控的因素。
     
      我同事最终设计了一套表结构,能够非常完善的解决我们所遇到的问题,且结构非常简单。
      
      完美解决方案:
      将每个sheet的数据分解为三部分:
      1:列信息表Column,主要记录列名称
      2:行信息表Row,主要记录行号
      3:数值信息Data,以列坐标以及行坐标能够在sheet上唯一确定一个数据,这里记录数据信息。

数据库表结构图如下:


      方案分析:
      1:将sheet中的所以列信息分别插入到Column表中,多少列就插入多少行记录,这样就能够无限支持列数据的增加,而不会受到表字段数量的限制。
      2:将行信息,对excel左侧对应的行号数据插入到Row中,有多少行就插入多少。
      3:最后是数据的存储,主要是利用二维坐标定位逻辑来确定数据。

4:尽管看起来一个sheet的数据分成三个表来存储,但每个表存储的内容都相当简单,逻辑清晰,所以不会带来更大的复杂性问题。

如何将数据库中的数据加载到内存中,我这里构建一个对象,此对象代表excel中的一行数据,如果是sheet所有数据可以用List<SheetData>来表示。ColumnInfo中的Key就是列名称,Value就是某一列的某一行的数据。按照我们的表结构,构建下面的对象模型也是比较容易的。

public  class SheetData
    {
       public List<ColumnInfo> Columns { get; set; }
    }
    public class ColumnInfo
    {
        public string  Key{get;set;}
        public string  Value{get;set;}
    }

如何绑定Email模板,既然我们有了明确的对象结构,那么应用xsl语法就更加容易了:

<table style="font-size:12;">
          <tr>
            <xsl:for-each select="Email/SheetData/Columns/ColumnInfo">
              <td style="background-color:#FFFF00;width:85px;">
                <xsl:value-of select="Key"/>
              </td >
            </xsl:for-each>
          </tr>
          <tr>
            <xsl:for-each select="Email/SheetData/Columns/ColumnInfo">
              <td>
                <xsl:value-of select="Value"/>
              </td >
            </xsl:for-each>
          </tr>
        </table>

上面的方案解决了之前方案的所有问题,由于存储数据的表结构是可知的,所以在数据库查询以及email模板的绑定上都不会有任何问题。

转载于:https://www.cnblogs.com/ASPNET2008/archive/2012/08/11/2633632.html

小项目之数据库设计经验分享相关推荐

  1. 典型的开发国内小项目没失败的经验分享

    我们分公司不大不小有100来号人,开发人员有几十个,也算在国内是不大不小的那种吧,公司有一个优点就是清一色用.NET开发,这也正好一些优点可以派上用处了,我比较讨厌弄Java就是一个字折腾死人,何必跟 ...

  2. SQL数据库设计经验

    关键字: sql数据库设计经验 一个成功的管理系统,是由:[50% 的业务 + 50% 的软件] 所组成,而 50% 的成功软件又有 [25% 的数据库 + 25% 的程序] 所组成,数据库设计的好坏 ...

  3. 【成长之路】本科比赛作品设计经验分享

    成长之路系列目录 1.应届毕业生成为博主后的阶段性总结 2.应届生的毕设经验 3.本科比赛经验分享 4.本科比赛作品设计经验分享 目录 前言 一.选题思路 二.整体设计 三.创新性设计 结束语 前言 ...

  4. 专访阿里陶辉:大规模分布式系统、高性能服务器设计经验分享

    专访阿里陶辉:大规模分布式系统.高性能服务器设计经验分享 发表于2014-06-27 16:25|18197次阅读| 来源CSDN|55 条评论| 作者魏伟 云计算Nginx开源 摘要:先后就职于在国 ...

  5. 数据库主备_数据库周刊40丨OceanBase官网上线开发者社区;人民日报关注易鲸捷;数据库迁移经验分享…...

    摘要:墨天轮数据库周刊第40期发布啦,每周1次推送本周数据库相关热门资讯.精选文章.干货文档.本周分享 OceanBase官网上线开发者社区:人民日报关注易鲸捷:2020中国系统架构师大会10月线上召 ...

  6. 一个画板十年工程师的PCB设计经验分享

    一个画板十年工程师的PCB设计经验分享 一个画板十年工程师的PCB设计经验分享_手机搜狐网 一般PCB基本设计流程如下:前期准备->PCB结构设计->PCB布局->布线->布线 ...

  7. mos管的rc吸收电路计算_RC吸收电路的设计经验分享

    原标题:RC吸收电路的设计经验分享 开关电源设计中,我们常常使用到一个电阻串联一个电容构成的RC电路, RC电路性能会直接影响到产品性能和稳定性.本文将为大家介绍一种既能降低开关管损耗,且可降低变压器 ...

  8. WindowsGUI自动化测试项目实战+辛酸过程+经验分享

    WindowsGUI自动化测试项目实战+辛酸过程+经验分享 一.前言 ⚜ 起因 ⚜ 项目要求 ⚜ 预研过程 ⚜⚜ 框架选型 ⚜⚜ 关于UIaotumation框架 ⚜ 预研成果 二.项目介绍

  9. 实际项目的数据库设计基本方法

    目录 实际项目的数据库设计基本方法 一. 数据库设计规范化方法 需求分析阶段(常用自顶向下) 概念结构设计阶段(常用自底向上) 逻辑结构设计阶段 物理设计阶段 数据库实施阶段 6.数据库运行和维护阶段 ...

最新文章

  1. 边缘计算有哪些关键技术?
  2. R语言实战应用精讲50篇(二十七)-时空数据分析-经验空间/时间均值(latex公式+R代码绘图)
  3. lvm 扩展根目录_Linux下lvm在线扩容步骤
  4. 简单工厂之简单模型(uml)
  5. 从论文到PPT,一键生成!从此报告不用愁!
  6. jmeter web监听结果_Jmeter性能测试
  7. 《Python编程从入门到实践》记录之函数编写指南
  8. 关掉magiskhide_最新版Magisk-v20.4刷入后找不到Magisk Hide怎么办+Magisk Hide开启教程
  9. pascal与其它语言代码书写的不同和pascal的快捷键
  10. iar c语言单片机指针,51单片机IAR编程示例
  11. ezd格式文件怎么打开_EPLAN Electric P8 中的 EDZ 文件格式
  12. nodejs下载 安装 配置环境
  13. Grafana 8重磅发布:统一警报、实时流、继续炫酷到底!
  14. 上古卷轴ol服务器正在维护,上古卷轴ol服务器在哪 | 手游网游页游攻略大全
  15. 使用VLC在web页面显示海康威视实时监控
  16. 用sync toy做增量备份
  17. 淡季累库,黑色短期高位震荡看待(20210104).PDF
  18. 区块链改革杭州闭门会议——分享链改机遇,探讨价值联动!
  19. php-fpm的重启方法
  20. JVM(二十二) -- 性能监控与调优(三) -- JVM监控及诊断工具--GUI篇

热门文章

  1. Tensorflow C++接口部署python深度学习训练模型
  2. scp的用法,包括windows和linux
  3. Vue防抖(三种方式)
  4. 熊猫烧香病毒幕后黑手曝光 网络世界高手对决一个月
  5. 浅谈四种常见的agv导航方式及各自的优缺点
  6. Linux命令--查看文件信息
  7. zkSnarks:证明问题到QAP的转换
  8. Unity5.0 天空盒(CubeMap)
  9. 碳云智能想做的,是规划生命路线
  10. 金融产品的不可能三角:收益性、风险性、流动性