WF是什麼,許多對NET技術有了解的人能說出一點,但又說不清楚
不論你認為WF是什麼,但不要與Jbpm ,Shark ,Biztalk,SharePoint 這些產品做比效,這些產品有共同的特點就是面向企業業務流程應用的產品,WF不是,WF面向的開發人員
WF是一個使用XML描述,具有IOC、AOP功能的面向流程控制的開發平台.
我從事工作流開發有8年了,學習WF已經有5年了,在博客園寫關於WF的主題博客也快4年了,自從接觸WF後我一直在解釋WF與傳統工作流之間的區別
可能是我即從事工作流開發,從學習WF,同時又用WF開發工作流,所以使很多看我博客的人誤認為WF就是象Jbpm ,Shark ,Biztalk,SharePoint 這些產品一樣專門用來開發企業業務流程的.
上面列出的文章標上了寫作日期,可以證明我一直在向大家說明這個問題,但現在看來是不夠的.所以我決定再寫一個系列,用一些具體應用來全面介紹一下WF
(以前寫過的內容我就不再重復了,想了解WF的朋友可以看一下上面列出的文章
如果是開發COM+的朋友,看了今天的例子,會發現這個例子的思路與用COM+構建數據邏輯層非常像.
其實WF3.X + WCF 就是一種替代COM+ 的方案, 但到了WF4.0 有些變化,MS提供了獨立的服務用於發布WCF與WF,這種方式比WF3.X + WCF更象COM+了,這些內容我以後再寫一個系列,下面看本文的例子
基於WF與WCF構建數據邏輯層
本文例子下載:
http://files.cnblogs.com/foundation/WFWCF.rar
項目說明
數據庫,在WFWCF.rar文件中
一般在構建企業應用時,會構建一個[數據邏輯層].通常的結構如下
本例將用一個簡單的例子講解一下基於WF與WCF構建[數據邏輯層]
先看一下本例中的數據庫結構
這是一個簡單的數據庫,但這個結構基本上是所用企業應用數據的初級模型
再說一下對數據的操作
對數據操從本質上講就是對表的[增,查,刪,改],其實對一個單表的[增,查,刪,改]是很簡單的,
我通常將傳統SQL[增,查,刪,改]方式操作一個表的工作量定為 ( 1 * 表的字段個數)
如果有10無關系張表,工作量就為 ( 1 * 表1的字段個數) + ( 1 * 表2的字段個數) ...( 1 * 表10的字段個數)
這種工作是簡單的,其實如果真的是這樣的結構,我就不構建[數據邏輯層]了,直接UI 到 數據庫,一個頁面對一張表.
然而事實上表與表之間存在一個叫(關系/約束)的東西,現在問題復雜了
假設
[表A.ID] 約束 [表B.ID]
那處理表[表A]時,要考慮[表B] ,處理表[表B]時,要考慮[表A] ,最大的問題是當添加[表A.ID] 約束 [表C.ID]時,之前為處理表[表A]的業務邏輯還要加入處理 [表C]的.
很多時候,真正處理數據的代碼很簡單,大量的時間都浪費在(關系/約束)的判斷上
在本例將,我將對數據庫的操作變為獨立的單表[增,查,刪,改]操作,將(關系/約束)的判斷交給WF去做
對表的操作代碼
TabB表的類結構
[DataContract()]
public class TableB
{
[DataMember()]
public string RowID
{ set; get; }
[DataMember()]
public string ID
{ set; get; }
[DataMember()]
public string Value
{ set; get; }
}
以下是幾個方法
public static class dbManage
{
static string connectionString = "Data Source=.;Initial Catalog=testDB;Integrated Security=True";
//表[TabA]中是否存在[ID]的記?
public static bool checkIDinTabA(string ID)
{
using (System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(connectionString))
{
con.Open();
var command = con.CreateCommand();
command.CommandText = string.Format("select ID from TableA where ID='{0}'", ID);
object obj = command.ExecuteScalar();
con.Close();
if (obj==null)
{
return false;
}
else
{
return true;
}
}
}
//表[TabB]中是否存在指定[RowID]的記錄
public static bool checkRowIDinTabB(string RowID)
{
using (System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(connectionString))
{
con.Open();
var command = con.CreateCommand();
command.CommandText = string.Format("select RowID from TableB where RowID='{0}'", RowID);
object obj = command.ExecuteScalar();
con.Close();
if (obj == null)
{
return false;
}
else
{
return true;
}
}
}
//向表[TabB]中添加記錄
public static void insertTabB(TableB row)
{
using (System.Data.SqlClient.SqlConnection con = new System.Data.SqlClient.SqlConnection(connectionString))
{
con.Open();
var command = con.CreateCommand();
command.CommandText = string.Format("insert into TableB (RowID,ID,Value) values ('{0}','{1}','{2}')", row.RowID, row.ID, row.Value);
command.ExecuteNonQuery();
con.Close();
}
}
}
(看了這段代碼,可能有人會說對數據庫操作不加異常捕獲,不加事務,不加鎖定嗎,因為是例子,所以省略了嗎.答案是異常捕獲,事務,鎖定都在WF中設計)
只有上面的代碼,是無法直接使用insertTabB(TableB row),因為RowID,與ID可能存在潛在的鍵沖突
所以[向表[TabB]中添加記錄]我們要做如下業務邏輯判斷
在WCF服務中用WF實現上面的業務邏輯
添加以下變量
添加一個流程圖
流程設計參照[向表[TabB]中添加記錄]我們要做的業務邏輯判斷
數據操作的客戶端
可以使用ASP.NET , Winform ,WPF ,silverlight , 本例中使用WPF在WPF客戶端添加對上面WCF服務的引用
UI設計
代碼
private void button1_Click(object sender, RoutedEventArgs e)
{
wcfServer.ServiceClient ser = new wcfServer.ServiceClient();
wcfServer.TableB row = new wcfServer.TableB();
row.ID = ID.Text;
row.RowID = RowID.Text;
row.Value = Value.Text;
string message= ser.insertData(row);
MessageBox.Show(message);
}
關於異常捕獲,事務,鎖定
WF提供了這些容器,具體的使用可參考我寫的[WF4.0 基礎篇]這個系列
本例只是在[flowChar]的最外層添加了一個異常捕獲,
效果說明