MIS系統,就是管理信息系統,是企業管理思想的體現。一個MIS系統做得好不好,不僅在於IT部門的水平有多高,更在於一個企業的管理先不先進,規不規範,企業的高層對MIS系統得認識有多深。
當然,有一個好的CIO,一個好的系統分析員,一個好的架構師,一個好的數據設計師,3~5個訓練有素,基本功過硬的程序員(至少要能熟練運用數組,鏈表,隊列,堆棧,要知道遞規,知道怎樣把遞規算法改爲非遞規算法,知道樹,二叉查找樹,知道窮舉法,貪婪法等),再加上一個美工,那是再好不過了。可惜,大部分的企業沒有這些人,或者這些人不全(至少我知道的企業如此,軟件公司除外),都是一個人頂幾個人用。像我,一個人既是系統分析員(直接和用戶打交道,搞清楚他們的需求),又是架構師(架構不好,那以後的修改可是非常痛苦的,不要認爲用戶的要求的是不變,有時候,一個星期,他就要變3次),又是做數據設計(搞MIS系統,如果不熟悉SQL,那可說不過去),又是編碼(分內之事),又作界面設計(雖然難看,但是沒人,你就得抗),系統測試(你寫的程序你不測試,誰測試?),有時還得給人裝裝機,換換硒鼓,調調IP。所以工作了好幾年,但水平一直提不高,也就是弄弄數據庫,見幾個表,然後打開Delphi,新建一個表單,拉幾個比如DbEdit之類的東東,在設置一下DataSource,放幾個按鈕,寫幾行Insert,Edit,Post之類的代碼。說是高級打字員,一點也不爲過。
就這樣敲了幾年的Begin,End,Insert,Edit,Post,Select,update,delete,發現了一個規律,就是我每天辛辛苦苦敲的這些東東,其實完全可以敲一次就可以了,其他地方拉過就是了,不就是對數據的增,刪,改麼?哪管你審覈,覈准,還不就是對數據中一個字段的修改?什麼權限不權限,還不就是設定一下,讓你看不看得到某個字段的內容?這樣一想,居然覺得自己以前好傻。
所有的這些,最終都是通過SQL語句實現的,整個過程可以這樣描述。
首先,用戶開始使用系統,於是我根據他/她的用戶名select field1,field2,... from table where .... order by ....,然後用戶開始新增或修改數據,新增時,我 insert into table(field1,field2,field3....) values(value1,value2,value3...),修改時,我update table set field1=value1,field2=value2...where ....刪除時,我delete from table where ....
再分析,發現這些select,update,delete們,也有共同的特點,就是都是由動作,對象,條件組成,比如,select * from table where conditon1 order by sequence,update table set field1=value where condition,delete from table where condition。
至於相關的業務流程,無非就在Insert,update,delete之前作判斷,是否exists某種condition,如果存在,就再做相應的insert,update或delete,或者讓這些Insert,update,delete動作不被執行。
如果將這些功能封裝爲一個或幾個類,其他地方只要調用這個類或者幾個類,那不就省事多了?說幹就幹,經過兩天的冥思苦想,基於SQL Server 2005,C#2.0,寫了下面的幾行代碼,我把它做爲一個文件,DBWR.cs。
//
//Privileges.cs
//
namespace EwEAI.Business.Interfaces.IT
{
//
//權限定義
//
public enum PrivilegeType
{
PrivilegeNone,
GrantInsert = 1,
DenyInsert = 2,
GrantUpdate = 11,
DenyUpdate = 12,
GrantDelete = 21,
DenyDelete = 22,
GrantRun = 31,
DenyRun = 32,
GrantPrint = 41,
DenyPrint = 42,
GrantSelect = 91,
DenySelect = 92
}
}
//
//DBWR.cs
//
//#define Debug
using System;
using System.Collections;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using EwEAI.Business.Interfaces.IT;
namespace EwEAI.Data
{
/// <summary>
/// DBWR:數據讀寫類
/// </summary>
public class DBWR
{
#region 構造函數
private DBWR()
{
InitSetting();
_ConnectionString = GetDbCononectionString();
}
private void InitSetting()
{
DbSetting.ReadXml(@"../settings/DbSettings.xml");
}
private DataSet DbSetting = new DataSet("DbSetting");
private string GetDbCononectionString()
{
DataTable table = DbSetting.Tables["DataBase"];
table.DefaultView.Sort = "Name ASC";
int index=table.DefaultView.Find("DBConStr");
if (index == -1)
return null;
return table.DefaultView[index]["Value"].ToString();
}
/// <summary>
/// 數據讀寫模塊的唯一實例
/// </summary>
public static DBWR Instance
{
get
{
if (_instance == null)
_instance = new DBWR();
return _instance;
}
}
private static DBWR _instance = null;
#endregion
#region 數據庫聯接
/// <summary>
/// 數據庫連接字符串
/// </summary>
public string ConnectionString
{
get
{
#if Debug
return "Data Source=EW-CLIENT;Initial Catalog=EwEAI;User Id=sa;password=yahong;Pooling=true;Max Pool Size=8;Min Pool Size=3";
#else
// return System.Configuration.ConfigurationManager.AppSettings["DBConStr"];
//return System.Configuration.ConfigurationSettings.AppSettings["DBConStr"];
return _ConnectionString;
#endif
}
}
private string _ConnectionString = null;
/// <summary>
/// 數據庫連接
/// </summary>
public SqlConnection Connection
{
get
{
return new SqlConnection(ConnectionString);
}
}
#endregion
#region 數據讀寫
/// <summary>
/// 構建某個表的選擇列表
/// </summary>
/// <param name="User"></param>
/// <param name="tableName"></param>
/// <param name="Where"></param>
/// <param name="Order"></param>
/// <param name="ColList"></param>
/// <returns></returns>
///
public string BuildSelectSQL(string User, string tableName, string Where, string Order,
string[] ColList/*null返回所有字段*/)
{
StringBuilder Result = new StringBuilder("");
//表判定
string TableSQL = "select 1 from TablePrivileges where tableName='" + tableName + "'"
+ " and UserName in(select UserName from UserTree('" + User + "',1))"
+ " and SelectPrivilege=" + ((int)PrivilegeType.DenySelect).ToString();
object isDeny = this.GetSingleValue(TableSQL);
if (isDeny != null)
return null;
DataTable ColTable = GetFieldList(tableName, User);
if (ColTable == null)
return null;
if (ColTable.Rows.Count == 0)
return null;
//字段判定
string DenyString = "select FieldName from FieldPrivileges where tableName='" + tableName + "'"
+ " and UserName in(select UserName from UserTree('" + User + "',1))"
+ " and SelectPrivilege=" + ((int)PrivilegeType.DenySelect).ToString();
DataTable DenyFieldsTable = this.ReadData(DenyString);
Hashtable DenyFields = new Hashtable(30);
if (DenyFieldsTable != null)
{
foreach (DataRow dr in DenyFieldsTable.Rows)
DenyFields.Add(dr[0].ToString(), dr[0].ToString());
DenyFieldsTable.Dispose();
}
Result.Append(" select ");
int FieldCount = 0;
for (int i = 0; i < ColTable.Rows.Count; i++)
{
string FieldName = ColTable.Rows[i][0].ToString();
if (DenyFields.Contains(FieldName))
continue;
//如果只返回部分字段
if (ColList != null)
{
int j = 0;
for (; j < ColList.Length; j++)
{
if (FieldName == ColList[j])
break;
}
if (j == ColList.Length)
continue;
}
Result.Append(FieldName);
FieldCount++;
if (ColList != null)
if (FieldCount == ColList.Length)
break;
if (i < ColTable.Rows.Count - 1)
Result.Append(",");
}
Result.Append(" from ");
Result.Append(tableName);
Result.Append(" ");
Result.Append(Where);
Result.Append(" ");
if (Order != null && Order != "")
{
Result.Append(" Order by ");
Result.Append(Order);
}
ColTable.Dispose();
return Result.ToString();
}
/// <summary>
/// 提取某個表的可以選擇字段
/// </summary>
/// <param name="tableName"></param>
/// <param name="User"></param>
/// <returns></returns>
private DataTable GetFieldList(string tableName, string User)
{
string ASQL = "select FieldName,(select Seq from Fields where tableName='"
+ tableName + "' and FieldName=O.FieldName)Seq from FieldPrivileges O"
+ " where UserName in (select UserName from UserTree('" + User + "',1))"
+ " and TableName='" + tableName + "'"
+ " and FieldName in(select FieldName from Fields where IsUserDefined=0)"
+ " order by Seq";
return this.ReadData(ASQL);
}
public void ExecSQL(string SQL)
{
SqlConnection con = Connection;
try
{
con.Open();
SqlCommand cmd = new SqlCommand(SQL, con);
cmd.ExecuteNonQuery();
cmd.Dispose();
}
finally
{
con.Close();
con.Dispose();
con = null;
}
}
public DataTable ReadData(string SQL)
{
SqlConnection con = Connection;
try
{
DataTable table = new DataTable();
SqlDataAdapter adapter = new SqlDataAdapter(SQL, con);
adapter.FillSchema(table, SchemaType.Source);
adapter.Fill(table);
adapter.Dispose();
return table;
}
finally
{
con.Dispose();
}
}
public DataTable ReadData(string SQL,ref DataTable table)
{
SqlConnection con = Connection;
try
{
SqlDataAdapter adapter = new SqlDataAdapter(SQL, con);
adapter.FillSchema(table, SchemaType.Source);
adapter.Fill(table);
adapter.Dispose();
return table;
}
finally
{
con.Dispose();
}
}
public DataTable GetStruct(string SQL)
{
SqlConnection con = Connection;
try
{
DataTable Result = new DataTable();
SqlDataAdapter adapter = new SqlDataAdapter(SQL, con);
adapter.FillSchema(Result, SchemaType.Source);
adapter.Dispose();
return Result;
}
finally
{
con.Dispose();
}
}
public object GetSingleValue(string SQL)
{
SqlConnection con = Connection;
try
{
con.Open();
SqlCommand cmd = new SqlCommand(SQL, con);
object Result = cmd.ExecuteScalar();
cmd.Dispose();
if (Result is DBNull)
return null;
return Result;
}
finally
{
con.Dispose();
}
}
public string Update(string ASQL, DataTable table)
{
string Result = "";
SqlConnection con = Connection;
SqlTransaction action = null;
try
{
using (SqlDataAdapter adapter = new SqlDataAdapter(ASQL, con))
{
using (SqlCommandBuilder cb = new SqlCommandBuilder(adapter))
{
con.Open();
cb.RefreshSchema();
adapter.UpdateCommand = cb.GetUpdateCommand();
adapter.DeleteCommand = cb.GetDeleteCommand();
adapter.InsertCommand = cb.GetInsertCommand();
action = con.BeginTransaction();
adapter.UpdateCommand.Transaction = action;
adapter.DeleteCommand.Transaction = action;
adapter.InsertCommand.Transaction = action;
adapter.Update(table);
action.Commit();
}
}
}
catch (Exception e)
{
Result = e.Message;
action.Rollback();
}
finally
{
con.Dispose();
action.Dispose();
action = null;
}
return Result;
}
public string Update(string ASQL, DataRow row)
{
string Result = null;
SqlConnection con = Connection;
try
{
using (SqlDataAdapter adapter = new SqlDataAdapter(ASQL, con))
{
using (SqlCommandBuilder cb = new SqlCommandBuilder(adapter))
{
adapter.Update(new DataRow[] { row });
}
}
}
catch (Exception e)
{
Result = e.Message;
}
finally
{
con.Dispose();
}
return Result;
}
private Hashtable GetAdapter(Hashtable SQLS,SqlConnection con)
{
Hashtable Result = new Hashtable(SQLS.Count);
foreach (string SQL in SQLS.Values)
{
SqlDataAdapter adapter = new SqlDataAdapter(SQL, con);
SqlCommandBuilder cb = new SqlCommandBuilder(adapter);
adapter.UpdateCommand = cb.GetUpdateCommand();
adapter.DeleteCommand = cb.GetDeleteCommand();
adapter.InsertCommand = cb.GetInsertCommand();
Result.Add(SQL, adapter);
}
return Result;
}
public string Update(DataSet businessData,Hashtable SQLS)
{
SqlConnection con = Connection;
SqlTransaction action = null;
Hashtable Adapters = new Hashtable();
try
{
Adapters=GetAdapter(SQLS,con);
con.Open();
action = con.BeginTransaction();
foreach (DataTable table in businessData.Tables)
{
try
{
if (table.GetChanges() == null)
continue;
string SQL = SQLS[table.TableName].ToString();
SqlDataAdapter adapter = (SqlDataAdapter)Adapters[SQL];
adapter.InsertCommand.Transaction = action;
adapter.UpdateCommand.Transaction = action;
adapter.DeleteCommand.Transaction = action;
adapter.Update(table.GetChanges());
}
catch (Exception cex)
{
if (!(cex is DBConcurrencyException))
{
throw cex;
}
}
}
action.Commit();
}
catch (Exception e)
{
action.Rollback();
return e.Message;
}
finally
{
foreach (SqlDataAdapter adater in Adapters.Values)
adater.Dispose();
Adapters.Clear();
con.Dispose();
action.Dispose();
action = null;
}
return null;
}
#endregion
}
}