摘 要:
随着MIS系统的建设,IT信息使用者们对信息的处理的要求也不断扩大,这必然影响到MNIS系统建设的变更管理,如何进行客户自定义的数据库和程序设计,让客户能够根据需要进行数据库内容维护,对于减少MIS系统建设项目变更,满足客户需求具有重要意义。本文提出一种在DotNet和Microsoft SqlServer下的解决方案实现客户自定义的数据库和程序设计方案。
关键词:
客户自定义、MIS、存储过程,
1、 引言
所谓MIS(管理信息系统--Management Information System)系统,是一个由人、计算机及其他外围设备等组成的能进行信息的收集、传递、存贮、加工、维护和使用的系统。它是一门新兴的科学,其主要任务是最大限度的利用现代计算机及网络通讯技术加强企业的信息管理,通过对企业拥有的人力、物力、财力、设备、技术等资源的调查了解,建立正确的数据,加工处理并编制成各种信息资料及时提供给管理人员,以便进行正确的决策,不断提高企业的管理水平和经济效益。目前,企业的计算机网络已成为企业进行技术改造及提高企业管理水平的重要手段。由于MIS系统建设经过可行性分析、用户调研、需求分析、系统分析、概要设计、详细设计、编码、测试、试运行和上线运行等多个阶段,周期一般比较长。
2、 客户自定义性设计问题的提出
由于MIS建设周期比较长,同时信息使用者往往对所建设的信息系统能够实现什么样的功能缺乏必要的了解,常常在版本提交进行试运行时,才发现原来并没有实现其所要求的功能或者要求添加新的功能,增加大量系统变更单,这必然导致系统的架构发生较大的变化,对于系统设计者和开发者来说,考虑到开发进度和工作量,并不能完全接受系统变更单,致使没有达到系统建设者预计目标,导致系统建设无限延期、费用超标,甚至系统建设失败。
这些变更常常是由于建设者当初没有考虑到更多因素,致使数据库设计中没有相应的字段。而设计者通常考虑到后续设计问题。一个通常的解决方案是,在数据库设计中我们添加若干个备用字段,以备系统扩展不时之需,但是在一个需要对字段进行安全授权的模式和对未来系统扩展的不确定性,无法估算出相应数据字段。况且,字段还需要不同的类型,这些类型分别存储不同类型数据,以备将来数据统计分析之用,所以最好的方法是在运行时由用户自定义来实现。
3、 客户自定义设计技术实现
客户自定义设计中设计的技术包括三个,一是如何让客户自定义数据库字段;二是如何对这些数据字段进行字段级授权,确保在MIS运行时,确保数据的安全性。三是系统用户如何获得其应得的数据集。我们以SqlServer 2005数据库和ASPNET2.0为例,来实现对自定义问题的解决。
3.1数据表、存储过程和触发器
3.1.1数据表知识
数据表的记录数随数据的增加而改变,但其字段数是相对固定的;二维表中的每一列均有唯一的字段名;二维表中不允许出现完全相同的两行二维表中行的顺序、列的顺序均可以任意交换。
3.1.2存储过程
存储过程式之封装了服务器中SQL语句集合的数据库对象。类似于其他编程语言中的过程。存储过程保存在数据库中,通常在在存储过程中保存业务逻辑。
3.1.3字段说明
由于需要根据存储过程生成动态的数据字段,程序中需要根据动态字段的字段名构造数据集的Header设置,我们一般利用数据库的说明作为数据集描述。所以需要在数据库修改时,设置字段的说明字段。
3.1.4sp_addextendedproperty过程和fn_listextendedproperty函数说明
sp_addextendedproperty将新扩展属性添加到数据库对象中,包含八个参数分别为扩展字段名称,扩展字段内容,类别名称,类别,对象名称,对象,属性名称和属性名。如为用户表test的ID字段设置说明为序号,调用方法如下:
sp_addextendedproperty 'MS_Description', '序号', 'user',dbo, 'table',test, 'column', 'id'。
fn_listextendedproperty返回数据库对象的扩展属性值。包含六个参数。其中第一个参数是需要读取扩展属性名称,第二个参数为用户或用户定义类型,第三个参数为架构名称,第四个参数为修改的对象一般为table,如第四个参数为table,则第五个参数为表名,第六个为需要读取对象,我们一般为列column,第七个为column具体列名称.如我们为dbo中表test中的列id的说明属性为:
fn_listextendedproperty ('MS_Description', 'USER', 'dbo', 'table', 'test', 'column', 'id')
3.2客户自定义数据库字段实现
为了实现动态定义数据库,需要两个表来定义数据表的结构。一个为数据表,用来保存实际的数据,第二个表用来记录这个数据表的结构和安全分配方式记为设置表。通过为设置表中添加记录,修改数据表的结构,实现对数据表的扩展。同时在修改设置表中可以为这个表的字段()设置相应的系统用户,在程序中控制用户可以实现对该字段的读写权限。
修改数据库表实际是通过动态调用Alter Table语句来实现的。在Alter Table语句中通过调用add、modify和drop分别实现对字段的添加、修改和删除。
为了在动态生成用户数据集时能够显示说明字段说明,需要在存储过程和函数中分别调用sp_addextendedproperty和fn_listextendedproperty分别设置和读取数据表字段的说明。
3.3实现动态数据填报数据集
我们根据登录用户设置,获取登录用户具有访问权限的数据表字段,根据这些字段构造动态读取数据表的Select语句,同时根据这些字段的描述,更新数据集中的字段的header属性,确保显示数据列的描述字段。
根据用户修改的字段,动态构造更新,确保其只能更新其相对应的数据字段。同时对数据库字段中设置一些公共字段,确保每个用户都可以访问。
4、 设备管理系统中设备月报自定义设计的实现
4.1 设置表维护页面实现
4.1.1 addcolumntosbyb存储过程的实现
编写了addcolumntosbyb存储过程实现对数据表的修改。代码如下:
CREATE PROCEDURE [dbo].[addcolumntosbyb]
@zdmc varchar(20), @zdms varchar(50), @sbybzdlx varchar(20),
@sbybzdcd int
AS
BEGIN
-- 定义运行参数,Sql为要运行的构造SQL语句,zdlx为字段类型
declare @sql nvarchar(4000)
declare @zdlx varchar(20)
if @sbybzdlx='字符'
set @zdlx=' varchar(' + cast(@sbybzdcd as varchar) + ')'
if @sbybzdlx='整数'
set @zdlx=' int'
if @sbybzdlx='日期'
set @zdlx=' datetime'
if @sbybzdlx='小数'
set @zdlx=' decimal(18.2)'
-- 构造更改数据库的SQL语句
set @sql = 'alter table sb_rcgl_sbyb add ' + @zdmc + @zdlx;
-- 执行SQL 语句更改数据库
execute sp_executesql @sql
-- 添加字段类型的说明描述
Execute sp_addextendedproperty 'MS_Description', @zdms,'user', dbo,'table', sb_rcgl_sbyb , 'column',@zdmc
END
4.1.2 sbybzd存储过程的实现
系统根据sb_rcgl_sbyb表的结构在数据记录表sb_rcgl_sbyb_xmfp中添加记录,记录该表的字段类型和安全访问模式。
Create PROCEDURE [dbo].[sbybzd] AS
BEGIN
-- 定义参数字段
-- @sbybzdms 设备月报字段描述
-- @sbybzdmc 设备月报字段名称
-- @type_name 设备月报字段类型
declare @sbybzdms varchar(50)
declare @sbybzdmc varchar(50)
declare @type_name varchar(50)
-- 判断是否存在临时表#temp,若果存在着删除之
if object_id('tempdb..#temp') is not null
drop table #temp
-- 创建临时表读取表SB_RCGL_SBYB的字段设置
create table #temp
(
table_qualifier varchar(20),table_owner varchar(20),table_name varchar(50),column_name varchar(20),
data_type int,type_name varchar(20),precision int,length int,scale int,radix int,
nullable int,remarks varchar(20),column_def varchar(20),sql_data_type int,sql_datetime_sub varchar(20),
char_octet_length int,ordinal_position int,is_nullable varchar(20),ss_data_type int
)
-- 将SB_RCGL_SBYB表的字段设置保存到临时表#temp中
insert into #temp exec sp_columns "SB_RCGL_SBYB"
-- 为每个字段设置其记录表项
declare sbybzdmc cursor for select column_name,type_name from #temp
open sbybzdmc
fetch sbybzdmc into @sbybzdmc,@type_name
WHILE @@FETCH_STATUS = 0
BEGIN
if @type_name='numeric'
set @type_name='小数'
if @type_name='bigint identity' or @type_name='int'
set @type_name='整数'
if @type_name='varchar' or @type_name='char'
set @type_name='字符'
-- 读取该字段的描述信息
select @sbybzdms=cast(value as varchar) from ::fn_listextendedproperty ('MS_Description', 'USER', 'dbo', 'table', 'sb_rcgl_sbyb', 'column', @sbybzdmc)
insert into sb_rcgl_sbyb_xmfp(xmmc,xmms,zdlx,zdcd,gy) select column_name,@sbybzdms,@type_name,length,'false' from #temp where column_name=@sbybzdmc and column_name not in ( select xmmc from sb_rcgl_sbyb_xmfp)
fetch sbybzdmc into @sbybzdmc,@type_name
END
-- 更新数据记录表中的数据内容
delete from sb_rcgl_sbyb_xmfp where xmmc not in (select column_name from #temp);
CLOSE sbybzdmc
deallocate sbybzdmc
END
4.1.3 页面增加数据行的逻辑过程
页面增加和管理数据行的页面如下:
当客户录入相应的数据字段后,单击新建按钮时,触发事件执行如下代码:
--读取录入内容并保存到数据库
TextBox tb_xmmc = GridView1.FooterRow.FindControl("tb_xmmc") as TextBox;
DropDownList ddl_fpr = GridView1.FooterRow.FindControl("ddl_fpr") as DropDownList;
TextBox tb_xmms = GridView1.FooterRow.FindControl("tb_xmms") as TextBox;
DropDownList ddl_zdlx = GridView1.FooterRow.FindControl("ddl_zdlx") as DropDownList;
TextBox tb_zdcd = GridView1.FooterRow.FindControl("tb_zdcd") as TextBox;
CheckBox cb_gy = GridView1.FooterRow.FindControl("cb_gy") as CheckBox;
if (tb_xmmc.Text == null | tb_xmmc.Text == "" | tb_xmms.Text == null | tb_xmms.Text == "" | ddl_zdlx.SelectedValue == null | tb_zdcd.Text == null | tb_zdcd.Text == "")
{
Label6.Text = "错误:必须输入字段名称,字段描述,字段类型和字段长度";
}
else
{
SqlDataSource1.InsertParameters["xmmc"].DefaultValue = tb_xmmc.Text;
SqlDataSource1.InsertParameters["xmms"].DefaultValue = tb_xmms.Text;
SqlDataSource1.InsertParameters["fpr"].DefaultValue = ddl_fpr.SelectedValue;
SqlDataSource1.InsertParameters["zdlx"].DefaultValue = ddl_zdlx.SelectedValue;
SqlDataSource1.InsertParameters["zdcd"].DefaultValue = tb_zdcd.Text;
SqlDataSource1.InsertParameters["gy"].DefaultValue = cb_gy.Checked.ToString();
SqlDataSource1.Insert();
-- 调用存储过程addcolumntosbyb将字段变化反映到表sb_rcgl_sbyb中
darkblue.data.sqlserver.SystemParameters.ExecuteScalarWithOneValue("execute addcolumntosbyb '" + tb_xmmc.Text + "','" + tb_xmms.Text + "','" + ddl_zdlx.SelectedValue + "'," + tb_zdcd.Text);
-- 调用存储过程sbybzd生成sb_rcgl_sbyb_xmfp数据记录
darkblue.data.sqlserver.SystemParameters.ExecuteScalarWithOneValue("execute sbybzd");
SqlDataSource1.DataBind();
GridView1.DataBind();
Label6.Text = "数据插入成功";
}
4.2 用户数据填报页面实现
当客户登录到用户填报页面时,页面构造其具有权限字段,进行填写并保存到数据库中。
4.2.1 构造当前用户可访问的字段集
页面中放入一个数据集,其中保存所有该客户可以访问的数据表sb_rcgl_sbyb中可以访问的字段。该Select语句如下:
SELECT [XMMC], [FPR], [XMMS], [ZDLX], [ZDCD] FROM [SB_RCGL_SBYB_XMFP] WHERE ([FPR] = @FPR and gy='false')
其中:@FPR为系统登录客户。
4.2.2 管理员根据业务需要设置字段用户。
如下图,为用户胡兰天设置仪表完好率、仪表投用率和仪表控制率字段进行填报。其中序号、年度、月份、本年期数和总期数为公用字段,由系统自动维护。为公用字段。只可以查看,不允许修改。
4.2.3 根据字段集动态生成需要客户录入控件
for (int i = 0; i < GridView2.Rows.Count; i++)
{
TextBox tb_1 = new TextBox();
Label lb_1 = new Label();
tb_1.ID = "tb_" + GridView2.Rows[i].Cells[0].Text;
lb_1.Text = GridView2.Rows[i].Cells[1].Text;
if (GridView2.Rows[i].Cells[2].Text == "字符")
{
tb_1.Width = System.Web.UI.WebControls.Unit.Pixel(600);
tb_1.Height = System.Web.UI.WebControls.Unit.Pixel(300);
tb_1.TextMode = TextBoxMode.MultiLine;
tb_1.Rows = 15;
}
if (GridView2.Rows[i].Cells[2].Text == "数字")
{
tb_1.Width = System.Web.UI.WebControls.Unit.Pixel(15);
tb_1.Height = System.Web.UI.WebControls.Unit.Pixel(15);
}
TableRow tb_row = new TableRow();
TableCell tb_cell = new TableCell();
tb_cell.Controls.Add(lb_1);
tb_cell.Controls.Add(tb_1);
tb_row.Cells.Add(tb_cell);
Table1.Rows.Add(tb_row);
}
页面录入如下:
4.2.4 根据需要动态生成更新语句
客户录入数据后,单击保存时触发如下事件代码:
string updatesql;
updatesql = "update sb_rcgl_sbyb set ";
string xh;
xh = GridView1.Rows[0].Cells[0].Text;
for (int i = 0; i < GridView2.Rows.Count; i++)
{
TextBox tb_1 = Table1.FindControl("tb_" + GridView2.Rows[i].Cells[0].Text) as TextBox;
if (GridView2.Rows[i].Cells[2].Text == "字符")
{
if (tb_1.Text=="")
{
updatesql = updatesql + GridView2.Rows[i].Cells[0].Text + "=' '" + ",";
}
else
{
updatesql = updatesql + GridView2.Rows[i].Cells[0].Text + "='" + tb_1.Text + "',";
}
}
else
{
if (tb_1.Text!="")
{
updatesql = updatesql + GridView2.Rows[i].Cells[0].Text + "=" + tb_1.Text + ",";
}
}
}
updatesql = updatesql.Substring(0,updatesql.Length - 1);
updatesql = updatesql + " where sbybxh=" + xh;
darkblue.data.sqlserver.SystemParameters.ExecuteScalarWithOneValue(updatesql);
GridView1.DataBind();
实现对所控制字段的填写。
5、 结束语
通过编写存储过程addcolumntosbyb和sbybzd,实现对数据记录表的修改实现对数据表结构的修改和对数据表字段的授权。通过页面编程实现登录用户对授权字段访问,确保客户对该字段访问。实现了对数据表字段的自定义修改