Database2Sharp生成的Enterprise Library架構對Oracle自動增長列欄位的支援

iDotNetSpace發表於2009-10-22

自動增長的主鍵欄位是個好東西,提供了一個比較有意義和可閱讀的欄位內容(相對GUID來說),插入的時候,不用管它的值,資料庫自動追加;但它也是一個不好的東西,如果管理不好,可能會造成衝突。本文暫且不討論其優劣,因為存在就是硬道理,很多時候,我們都是採用自增長欄位的,特別是對於SqlServer資料開發來說。

 本文闡述一下在Database2Sharp(軟體下載地址:http://www.iqidi.com/database2sharp.htm生成的Enterprise Library架構如何實現Oracle的自增長的支援。同時也會順帶說說對SqlServer、Access的實現。

 Database2Sharp生成的Enterprise Library架構其實對Oracle內建了對自增長序列的支援,在資料庫訪問層的基類BaseDAL中,我們看到下面的程式碼。

     /// 

    /// 資料訪問層的基類
    
/// 
    public abstract class BaseDAL<T> : IBaseDAL<T> where T : BaseEntity, new()
    {
        
#region 建構函式

        
protected string tableName;//需要初始化的物件表名
        protected string primaryKey;//資料庫的主鍵欄位名
        protected string sortField = "ID";//排序欄位
        private bool isDescending = false;//

        
protected string selectedFields = " * ";//選擇的欄位,預設為所有(*)
        private string seqField = "";//指定那個欄位是用序列來控制它的值的,一般為主鍵
        private string seqName = "";//指定的序列名稱,建議規則為:SEQ_表名稱
        
        
/// 
        
/// 指定那個欄位是用序列來控制它的值的,一般為主鍵
        
/// 
        public string SeqField
        {
            
get { return seqField; }
            
set { seqField = value; }
        }

        
/// 
        
/// 指定的序列名稱,建議規則為:SEQ_表名稱
        
/// 
        public string SeqName
        {
            
get { return seqName; }
            
set { seqName = value; }
        }


這段程式碼定義了兩個屬性,一個是序列欄位名稱(一般是主鍵,如ID),一個是我們為該欄位指定的序列物件名稱,我們這裡建議的名稱是"SEQ_表名稱",當然也可以使用任意的名稱,合理統一就可以了。這兩個屬性在基類不需要修改,只需要在具體的資料訪問物件(如資料訪問層中的Customer類)建構函式中,指定序列欄位和序列物件即可。

下面我們看看錶盒序列的指令碼程式碼,例如我建立一個客戶表,其欄位ID為自增序列,我的建立指令碼是。

 create table ALL_CUSTOMER

(
  ID          NUMBER not null,
  USERNUMBER  VARCHAR2(50),
  NAME        VARCHAR2(50),
  TYPE        VARCHAR2(50),
  AREA        VARCHAR2(50),
  COMPANY     VARCHAR2(50),
  ADDRESS     VARCHAR2(50),
  TELEPHONE1  VARCHAR2(50),
  TELEPHONE2  VARCHAR2(50),
  TELEPHONE3  VARCHAR2(50),
  TELEPHONE4  VARCHAR2(50),
  TELEPHONE5  VARCHAR2(50),
  CREATEDATE  DATE,
  SHOP_ID     VARCHAR2(50),
  NOTE        VARCHAR2(255),
  LASTUPDATED DATE,
  
constraint PK_ALL_CUSTOMER primary key (ID)
);

create sequence SEQ_ALL_CUSTOMER
minvalue 1
maxvalue 999999999999999999999999999
start with 1220
increment by 1
cache 20;

commit;

 

注意SEQ_ALL_CUSTOMER就是序列物件名稱,那麼我們再插入的時候,應該如何寫入序列欄位的值,並且獲得新的值作為返回值的呢?

在BaseDAL中,有一個Insert2的方法,是專門處理 自增序列函式,並且返回建立記錄的自增欄位的值的,我們來看看其原始碼。

         /// 

        /// 新增記錄
        
/// 
        
/// Hashtable:鍵[key]為欄位名;值[value]為欄位對應的值
        
/// 需要操作的目標表名稱
        
/// 事務物件,如果使用事務,傳入事務物件,否則為Null不使用事務
        public int Insert2(Hashtable recordField, string targetTable, DbTransaction trans)
        {
            
int result = -1;
            
string fields = ""// 欄位名
            string vals = ""// 欄位值
            if (recordField == null || recordField.Count < 1)
            {
                
return result;
            }

            List<OracleParameter> paramList = new List<OracleParameter>();
            IEnumerator eKeys = recordField.Keys.GetEnumerator();

            
while (eKeys.MoveNext())
            {
                
string field = eKeys.Current.ToString();
                fields += field + ",";
                
if (!string.IsNullOrEmpty(seqField) && !string.IsNullOrEmpty(seqName)
                    
&& (field == seqField))
                {
                    vals += string.Format("{0}.NextVal,", seqName);
                }
                
else
                {
                    vals += string.Format(":{0},", field);
                    
object val = recordField[eKeys.Current.ToString()];
                    paramList.Add(new OracleParameter(":" + field, val));
                }
            }

            fields = fields.Trim(',');//除去前後的逗號
            vals = vals.Trim(',');//除去前後的逗號
            string sql = string.Format("INSERT INTO {0} ({1}) VALUES ({2})", targetTable, fields, vals);

            Database db = DatabaseFactory.CreateDatabase();
            DbCommand command = db.GetSqlStringCommand(sql);
            command.Parameters.AddRange(paramList.ToArray());

            
if (trans != null)
            {
                db.ExecuteNonQuery(command, trans);

                sql = string.Format("SELECT {0}.Currval ID From Dual", seqName);
                command = db.GetSqlStringCommand(sql);
                result = Convert.ToInt32(db.ExecuteScalar(command, trans).ToString());
            }
            
else
            {
                db.ExecuteNonQuery(command);

                sql = string.Format("SELECT {0}.Currval ID From Dual", seqName);
                command = db.GetSqlStringCommand(sql);
                result = Convert.ToInt32(db.ExecuteScalar(command).ToString());
            }

            
return result;
        }

 

其中我們判斷是否有自增序列ID和其名稱(非空字元),如果有則使用這段程式碼,來寫入自增序列的下一個值NextVal(新增值),作為這個欄位的值。

vals += string.Format("{0}.NextVal,", seqName); 

 如果要返回插入的自增序列值,那麼我們使用序列物件的Currval 就可以了。下面是返回插入的欄位內容。

sql = string.Format("SELECT {0}.Currval ID From Dual", seqName); 

這樣對於寫入新的自增長值並返回就實現了。


對SqlServer和Access自增長欄位的支援 

對於SqlServer,實現自增長欄位就更加方便了,由於沒有Oracle序列物件那麼麻煩,所以只需要在具體的資料庫訪問物件中,構建寫入欄位的Hash表中,忽略該欄位就可以了(程式碼已經自動生成,不用管理的)。其返回剛剛插入的自增內容,則在插入的語句後面增加一條語句就可以了,語句如下。

 SELECT SCOPE_IDENTITY()

對於Access的資料庫,原理和SqlServer一樣,不過需要返回剛剛插入的自增長值的時候,使用這段語句就可以了。

 SELECT @@IDENTITY

 對於SqlServer和Access,只要設計好資料庫的自增欄位,自動生成的程式碼中,資料訪問類是不用修改任何資訊,就可以完美支援自增序列。

 

Database2Sharp生成的Enterprise Library架構對Oracle自動增長列欄位的支援主要研究技術:程式碼生成工具、Visio二次開發
    
    轉載請註明出處:
Database2Sharp生成的Enterprise Library架構對Oracle自動增長列欄位的支援撰寫人:伍華聰  http:
//www.iqidi.com 

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-617184/,如需轉載,請註明出處,否則將追究法律責任。

相關文章