數據存儲引擎是本項目里比較有特色的模塊。
特色一,使用接口來對應不同的數據庫。數據庫可以是Oracle、Sqlserver、MogoDB、甚至是xml文件。采用接口進行對應:
1 public interface IWorkflowDB 2 { 3 List<Flow> GetFlows(); 4 bool SaveFlow(Flow flow); 5 bool DeleteFlow(Guid flowId); 6 7 FlowInstance GetFlowInstanceByInstanceId(Guid flowInstanceId); 8 List<FlowInstance> GetFlowInstanceByFlowId(Guid flowId); 9 bool SaveFlowInstance(FlowInstance flowInstance);10 List<FlowInstance> GetFlowInstancesListByUser(Person person = null);11 bool DeleteFlowInstanceByInstanceId(Guid flowInstanceId);12 13 bool SaveForm(Form form);14 bool DeleteForm(Guid formId);15 List<Form> GetFormList();16 17 bool AddStep(WorkflowStep workflowStep);18 bool DeleteStep(Guid stepId);19 List<WorkflowStep> GetStepList();20 21 bool AddBaseTable(WorkflowConstant.BaseTable baseTable, Dictionary<int, string> values);22 Dictionary<int, string> GetBaseTableData(WorkflowConstant.BaseTable baseTable);23 bool DeleteBaseTableValue(WorkflowConstant.BaseTable baseTable, int key);24 }View Code
特色二,使用Oracle的SYS.XMLTYPE來存儲數據,查詢時使用輔助方法,或者XML查詢表達式
這樣系統里一共只用了四個表,包括一個臨時表,每個表不超過三個字段。
WORKFLOW_SETTINGS表:(存儲系統設置參數、流程等)
WORKFLOW_FORM表:(存儲系統表單)
WORKFLOW_FLOW表:(存儲流程實例)
還有一個temp表,一行一列,字段為CLOB類型。
XMLType里面存儲的是什么呢?不錯,正是各個類的實例,序列化后的字符:
實際存儲的方式:
保存時:類的實例-->XML序列化-->直接用Oracle的XMLtype存儲;
讀取時:讀出數據-->反序列化-->類的實例直接可用。
這樣就能方便的解決實體模型或領域模型與數據庫存儲之間“阻抗不匹配的”的問題。而且XMLType可以被SQLServer等主流數據庫支持,所以遷移到其他數據庫也很方便;如果你要使用常規的建表規則進行存儲,只要實現IWorkflowDB接口即可。
序列化反序列化的方法,使用了擴展方法,可以放在項目里任何一個靜態類里:
1 public static string ToSerializableXML<T>(this T t) 2 { 3 XmlSerializer mySerializer = new XmlSerializer(typeof (T)); 4 StringWriter sw = new StringWriter(); 5 mySerializer.Serialize(sw, t); 6 return sw.ToString(); 7 } 8 9 public static T ToEntity<T>(this string xmlString)10 {11 var xs = new XmlSerializer(typeof (T));12 var srReader = new StringReader(xmlString);13 var steplist = (T) xs.Deserialize(srReader);14 return steplist;15 }View Code
注意:有些類不能被序列化,比如Dictionary<TKey,TValue>,需要自己寫可序列化的類。
好啦,接下來是實現IWorkflowDB接口的OracleWorkFlowDBUtility類,以存儲工作流表單為例:
存儲:
1 public bool SaveForm(Form form) 2 { 3 var formContent = form.FormContent; 4 var formId = form.FormId; 5 form.FormContent = string.Empty; 6 7 var sql = string.Empty; 8 9 DbHelperOra.ExecuteSql("truncate table WORKFLOW_TEMP");10 var para = new OracleParameter("formInfo", OracleType.Clob);11 para.Value = form.ToSerializableXML();12 DbHelperOra.ExecuteSql("insert into WORKFLOW_TEMP(content) values (:formInfo)", para);13 14 var paras = new[]15 {16 new OracleParameter("formId", formId.ToString()),17 new OracleParameter("formContent", formContent)18 };19 if (DbHelperOra.GetSingle("select count(*) from WORKFLOW_FORM where form_id = :formId",20 new OracleParameter("formId", formId.ToString())).ToString() == "1")21 {22 sql =23 "update WORKFLOW_FORM set FORM_INFO = (select sys.xmlType.createXML(WORKFLOW_TEMP.content) from WORKFLOW_TEMP), FORM_CONTENT = :formContent where FORM_ID = :formId";24 }25 else26 {27 sql =28 "insert into WORKFLOW_FORM(FORM_ID,FORM_INFO,FORM_CONTENT) values (:formId,(select sys.xmlType.createXML(WORKFLOW_TEMP.content) from WORKFLOW_TEMP),:formContent)";29 }30 31 return DbHelperOra.ExecuteSql(sql, paras).ToString() == "1";32 }View Code
讀取:
1 public List<Form> GetFormList() 2 { 3 var ds = 4 DbHelperOra.Query( 5 "select t.form_info.getclobval() form_info, form_content from WORKFLOW_FORM t"); 6 if (ds != null) 7 { 8 var forms = new List<Form>(ds.Tables[0].Rows.Count); 9 foreach (DataRow dr in ds.Tables[0].Rows)10 {11 var str = dr["form_info"].ToString();12 var form = str.ToEntity<Form>();13 form.FormContent = dr["form_content"].ToString();14 forms.Add(form);15 }16 return forms;17 }18 return null;19 }View Code
刪除:
1 public bool DeleteForm(Guid formId) 2 { 3 try 4 { 5 if(DbHelperOra.ExecuteSql("delete from WORKFLOW_FORM where form_id = :formid", 6 new OracleParameter("formid", formId.ToString())).ToString(CultureInfo.InvariantCulture)=="1") 7 return true; 8 return false; 9 }10 catch (Exception ex)11 {12 return false;13 }14 }View Code
一切都很簡單,沒有惱人的一列列字段名,也不用ORM、代碼生成器等,開發、維護效率大幅度提高。
數據訪問類實例化在WorkflowService類里面
先定義私有變量:
PRivate readonly IWorkflowDB _iWorkflowDb;
然后在類的構造函數里這么寫:
新聞熱點
疑難解答