摘要: 我们常常要在web上显示流程图,网上比较难找,到处要收费,自己琢磨了一个,
比较简单,包括开始节点,结束结点,两种节点框图(节点、容器)和两种特殊线(跳线、返回线),
使用xml文件或xml字串作为数据源,
没有多少需求分析,给有心人参考,也收集一些建议,源码过段时间整理再放上。
阅读全文
来源:赛迪网 作者:Alice
数据表的设计原则:
(1)不应针对整个系统进行数据库设计,而应该根据系统架构中的组件划分,针对每个组件所处理的业务进行组件单元的数据库设计;不同组件间所对应的数据库表之间的关联应尽可能减少,如果不同组件间的表需要外键关联也尽量不要创建外键关联,而只是记录关联表的一个主键,确保组件对应的表之间的独立性,为系统或表结构的重构提供可能性。
(2)采用领域模型驱动的方式和自顶向下的思路进行数据库设计,首先分析系统业务,根据职责定义对象。对象要符合封装的特性,确保与职责相关的数据项被定义在一个对象之内,这些数据项能够完整描述该职责,不会出现职责描述缺失。并且一个对象有且只有一项职责,如果一个对象要负责两个或两个以上的职责,应进行分拆。
(3)根据建立的领域模型进行数据库表的映射,此时应参考数据库设计第二范式:一个表中的所有非关键字属性都依赖于整个关键字。关键字可以是一个属性,也可以是多个属性的集合,不论那种方式,都应确保关键字能够保证唯一性。在确定关键字时,应保证关键字不会参与业务且不会出现更新异常,这时,最优解决方案为采用一个自增数值型属性或一个随机字符串作为表的关键字。
(4)由于第一点所述的领域模型驱动的方式设计数据库表结构,领域模型中的每一个对象只有一项职责,所以对象中的数据项不存在传递依赖,所以,这种思路的数据库表结构设计从一开始即满足第三范式:一个表应满足第二范式,且属性间不存在传递依赖。
(5)同样,由于对象职责的单一性以及对象之间的关系反映的是业务逻辑之间的关系,所以在领域模型中的对象存在主对象和从对象之分,从对象是从1-N或N-N的角度进一步主对象的业务逻辑,所以从对象及对象关系映射为的表及表关联关系不存在删除和插入异常。
(6)在映射后得出的数据库表结构中,应再根据第四范式进行进一步修改,确保不存在多值依赖。这时,应根据反向工程的思路反馈给领域模型。如果表结构中存在多值依赖,则证明领域模型中的对象具有至少两个以上的职责,应根据第一条进行设计修正。第四范式:一个表如果满足BCNF,不应存在多值依赖。
(7)在经过分析后确认所有的表都满足二、三、四范式的情况下,表和表之间的关联尽量采用弱关联以便于对表字段和表结构的调整和重构。并且,我认为数据库中的表是用来持久化一个对象实例在特定时间及特定条件下的状态的,只是一个存储介质,所以,表和表之间也不应用强关联来表述业务(数据间的一致性),这一职责应由系统的逻辑层来保证,这种方式也确保了系统对于不正确数据(脏数据)的兼容性。当然,从整个系统的角度来说我们还是要尽最大努力确保系统不会产生脏数据,单从另一个角度来说,脏数据的产生在一定程度上也是不可避免的,我们也要保证系统对这种情况的容错性。这是一个折中的方案。
(8)应针对所有表的主键和外键建立索引,有针对性的(针对一些大数据量和常用检索方式)建立组合属性的索引,提高检索效率。虽然建立索引会消耗部分系统资源,但比较起在检索时搜索整张表中的数据尤其时表中的数据量较大时所带来的性能影响,以及无索引时的排序操作所带来的性能影响,这种方式仍然是值得提倡的。
(9)尽量少采用存储过程,目前已经有很多技术可以替代存储过程的功能如“对象/关系映射”等,将数据一致性的保证放在数据库中,无论对于版本控制、开发和部署、以及数据库的迁移都会带来很大的影响。但不可否认,存储过程具有性能上的优势,所以,当系统可使用的硬件不会得到提升而性能又是非常重要的质量属性时,可经过平衡考虑选用存储过程。
(10)当处理表间的关联约束所付出的代价(常常是使用性上的代价)超过了保证不会出现修改、删除、更改异常所付出的代价,并且数据冗余也不是主要的问题时,表设计可以不符合四个范式。四个范式确保了不会出现异常,但也可能由此导致过于纯洁的设计,使得表结构难于使用,所以在设计时需要进行综合判断,但首先确保符合四个范式,然后再进行精化修正是刚刚进入数据库设计领域时可以采用的最好办法。
(11)设计出的表要具有较好的使用性,主要体现在查询时是否需要关联多张表且还需使用复杂的SQL技巧。
(12)设计出的表要尽可能减少数据冗余,确保数据的准确性,有效的控制冗余有助于提高数据库的性能。
表 tree
字段 master
sub
sales
insert into tree values
('主1', '主2', 15);
insert into tree values
('主1', '主3', 20);
insert into tree values
('主2', '主4', 5);
insert into tree values
('主2', '主5', 10);
insert into tree values
('主3', '主5', 30);
insert into tree values
('主3', '主6', 40);
SQL> select * from tree;
MASTER SUB SALES
---------- ---------- ----------
主1 主2 15
主1 主3 20
主2 主4 5
主2 主5 10
主3 主5 30
主3 主6 40
如果用树型结构表示如下:
'主1'
-'主2'
--'主4'
--'主5'
'主1'
-'主3'
--'主5'
--'主6'
SQL> select * from tree
start with sub='主2' --相当于普通sql的where条件
connect by prior master=sub; --遍历的顺序是sub先于master遍历,也就是说从sub往上遍历一直到master(根节点)
2
MASTER SUB SALES
---------- ---------- ----------
主1 主2 15
SQL> select * from tree
start with master='主2'
connect by prior master=sub; --sub往上遍历至根节点(参考一下树型图)
2 3
MASTER SUB SALES
---------- ---------- ----------
主2 主4 5 --这条是自己本身,也就是第一遍遍历
主1 主2 15 --这是第2次遍历,我们从树型图可以看到,'主2'往上遍历是'主1'
主2 主5 10
主1 主2 15
好,我们关看上面可能还是不好理解,我们加入一个树结构专用函数sys_connect_by_path,便于理解
SQL> select sys_connect_by_path(MASTER,'/') from tree --master表示我遍历的起点只找在master列中存在的,如下例只要'主2'为起点,并以/为分割符
start with master='主2'
connect by prior master=sub; --往根节点遍历
2 3
SYS_CONNECT_BY_PATH(MASTER,'/')
--------------------------------------------------------------------------------
/主2 --第1遍遍历
/主2/主1 --第2遍遍历
/主2 --第2条master='主2'的记录的第1次遍历
/主2/主1 --第2条master='主2'的记录的第2次遍历
SQL> select sys_connect_by_path(MASTER,'/') from tree --起点为sub='主5'时MASTER=主2,主3
start with sub='主5'
connect by prior master=sub;
2 3
SYS_CONNECT_BY_PATH(MASTER,'/')
--------------------------------------------------------------------------------
/主2
/主2/主1
/主3
/主3/主1
SQL> select sys_connect_by_path(MASTER,'/'),sub,master from tree
start with sub is not null
connect by prior master=sub;
2 3
SYS_CONNECT_BY_PATH(MASTER,'/' SUB MASTER
------------------------------ ---------- ----------
/主1 主2 主1 --找主1到根的路径,这里根是主1他自己
/主1 主3 主1
/主2 主4 主2
/主2/主1 主2 主1 --找主2到根的路径,这里根是主1
/主2 主5 主2
/主2/主1 主2 主1
/主3 主5 主3
/主3/主1 主3 主1
/主3 主6 主3
/主3/主1 主3 主1
select sys_connect_by_path(MASTER,'/'),sub,master from tree
start with sub is not null
connect by prior sub = master;
SYS_CONNECT_BY_PATH(MASTER,'/' SUB MASTER
------------------------------ ---------- ----------
/主1 主2 主1
/主1/主2 主4 主2
/主1/主2 主5 主2
/主1 主3 主1
/主1/主3 主5 主3
/主1/主3 主6 主3
/主2 主4 主2
/主2 主5 主2
/主3 主5 主3
/主3 主6 主3
--------------------
SELECT *
FROM
(
SELECT b.bomid,
b.partno, b.version AS partversion, a.componentno, a.version AS componentversion,
a.alternativegroup, a.itemno, a.flag, a.referencepercentage, a.actualpercentage
FROM bomdetail a
INNER JOIN bommaster b ON a.bomid = b.bomid
WHERE to_date('2008-4-25', 'yyyy-mm-dd hh24:mi:ss') BETWEEN a.validfrom AND a.validto
AND to_date('2008-4-25', 'yyyy-mm-dd hh24:mi:ss') BETWEEN b.validfrom AND b.validto
)
START WITH partno = 'P01' AND partversion = 'AX'
CONNECT BY PRIOR componentno = partno AND componentversion = partversion
ORDER BY partno, partversion, componentno, componentversion, itemno;
--sql server 使用CTE
As we talked about it this morning, one of 23 GoF Design Pattern that is rarely used, but I think it's a good design...
http://www.codeproject.com/KB/architecture/AOMStrategies.aspx
http://www.codeproject.com/KB/architecture/GhostLoadingDataMapping.aspx
某世界500强制造企业软件开发部门招聘:
工作地点: 深圳
工作性质: 全职
发布时间: 2008-03-05
请把简历发送到: 410377712@qq.com
.net测试小组长
职位描述:
1. Web产品功能测试,包括测试用例设计,测试执行,测试bug的跟踪等。
2 .测试环境的布置和维护,建立与集成产品生产线自动测试环境,根据测试需求编写测试软件代码 。
3.测试工具的改进和维护。
4. 管理一个3~4人的测试组。
资格要求:
1.熟悉WEB产品测试,能设计测试用例,有相关工作经验者优先。
2.熟悉测试流程和BUG跟踪流程。
3.熟悉HTTP协议,有CMMI经验优先。
4.有.net开发经验1年,测试经验1年以上。
5.了解编程知识,了解C,c#语言。
6.易于沟通,善于交流,刻苦耐劳,有责任心。
7. 本科学历,相关专业,英语水平自认为还行。
.net开发小组长
1、参与公司网站的策划提出合理化的意见;
2、根据策划案的相关要求通过程序实现;
3、与前台设计处沟通与协作;
4、参与维护、支持阶段的工作;
5、完成程序设计处交办的其他工作;
6、带领3~4人开发团队。
任职资格:
1、计算机相关专业本科以上学历,有CMMI经验优先;
2、精通ASP.NET\C#\Java scvipt \SQL server\oracle
3、能独立完成网站建设、电子商务网站开发两年以上实战经验;
4、具有团队精神,沟通能力强,踏实肯干,善钻研;
5、自学能力强,有创新精神,善于沟通,有团队精神和责任心。
注意说明:
1.工资水平公司会根据学历、工作经验、能力等制定,我只能提供一个大概的,毕业2~4年本科毕业生一般4.5~7w
2.这次招聘面对有经验、高层次一点的,初学者请不要浪费时间。
1、建一个数据集,拖两个表进入
2、建立一新的报表,引用数据集的字段,这里来自两个表
3、在页面中拖入ReportViewer控件,添加上面建立的报表
4、在后台代码的page_load事件中写入
string orderid = "10249";
DataSet myds = new DataSet();
if(this.Request.QueryString["id"]!=null)
orderid=this.Request.QueryString["id"].ToString();
ReportParameter rptParaA = new ReportParameter("POrderID", orderid);
ReportViewer1.LocalReport.SetParameters(new ReportParameter[] { rptParaA });
myds = Fih.DBFramework.DbHelperSQL.ExecuteDataSet("select * from orders as a join Customers as b on a.CustomerID=b.CustomerID where a.orderid=" + orderid);
ReportViewer1.Visible = true;
ReportDataSource rds = new ReportDataSource("DataSet1_Orders", myds.Tables[0]);
ReportDataSource rds1 = new ReportDataSource("DataSet1_Customers", myds.Tables[0]);
ReportViewer1.LocalReport.DataSources.Clear();
ReportViewer1.LocalReport.DataSources.Add(rds);
ReportViewer1.LocalReport.DataSources.Add(rds1);
ReportViewer1.LocalReport.Refresh();
这样就可以从地址栏中传参数显示单条记录报表