權限管理系統 頁面權限粒度控制設計 GUID在數據庫系統的應用

轉自 http://www.cnblogs.com/zyx_blog/articles/2365967.html

系統頁面權限粒度控制設計

系統頁面權限粒度控制設計

 

說明:

表說明

  • Users 用戶表
  • Depts部門表
  • Roles角色表
  • Menus菜單表
  • Pages系統頁面
  • Actions各個頁面中的操作權限和菜單操作權限
  • RelationUser_Role用戶與角色的關係表
  • RelationRole_Action 角色與操作的關係表
  • RelationUser_Action 用戶與操作的關係
  • RelationDept_Action部門與操作的關係

權限業務

  • 默認用戶只能擁有角色,通過角色獲得操作權限.
  • 但是在實際應用中部門,用戶都可以具備特殊的操作權限.
  • 此設計即可實現用戶通過角色,部門,本身獲得操作權限.

解決方式

通過獲取3張權限關係表中數據,最後合併權限,即是當前用戶所具備的系統操作權限和菜單操作權限

 

圖1



GUID在數據庫系統的應用

 What‘s GUID ?

    GUID 是個根據網絡卡MAC Address 及時間等因素隨機產生的 128 Bits(=16 Bytes) 數字, 因爲 2 的128 次方是個極大的數目, 因此發生重複的機率非常非常.... 低 (樂觀地說: 樂透中獎的機率遠遠高於 GUID 重複, 我們可以假設 "不可能" 發生)!

    摘錄幾個網絡上流傳的例子來說明 GUID 如何地"不太可能" 發生重複:

    一. The probability of an accidental match is (theoretically - and I use that term guardedly) the same as throwing a set of 128 pennies,   and having them all land in the same heads/tails combination twice.
    (把128 個硬幣往上拋出落地後, 所有硬幣必須出現兩次完全相同 "人頭" 與 "數字" 的組合)

    二. 如果一臺機器每秒鐘產生10,000,000 個GUID, 則可以保證(機率意義上) 3,240 年不會發生重複!

    三. 全世界有60 億人口, 每個人每秒分配10 億個號碼, 那麼需要分配1800 億年! 反正等到地球毀滅了都不會用完的!

    把 GUID 以字符串形式表達就會像 "12345678-1234-1234-1234-123456789012" (4 Bits 代表一個字符, 則有32 個字符, 加上4 條短線共有36 個字符的長度)!

    The challenges of designing database.

    在傳統信息系統的數據庫端普遍存在幾個設計上的難題, 爲了解決這些題目, 開發團隊經常需要付出較高代價! 這些難題包括:

    一. ID (在此指概指在資料表中用來代表資料唯一性的字段) 值是否允許變更(例如: 部門編號, 產品編號, .....) ? ID 字段總是被使用與其它資料表關聯, 因此, 需要先判斷關聯是否已經存在, 以做爲 ID 字段可否變更的依據! 當 ID 字段關聯的對象數目過多時, 需要在判斷上付出更多成本!

    二. 由複合字段形成資料表關聯時, 是否需要對更多字段進行變更前的判斷或處理? 

    複合字段組成索引的典型之一是單據明細 (或稱 "分錄", 或指 Detail data, 其主索引可能由單據編號及明細序號(流水號) 組成)! 當某筆明細資料前方插入或是刪除另一筆明細時, 原有的明細序號是否需要變更? 不變更時明細序號是否連號且不重複? 變更後是否會破壞原有與其它資料的關聯? 
這可能是個取捨兩難的問題: 由於明細資料前方插入或刪除另一筆明細資料時, 在後方的所有明細資料的序號 "被迫" 遞增或遞減 (就像棒球在滿壘狀況下, 觸身球會造成三壘跑者被 "強迫" 擠回本壘得分), 則索引值會發生變化, 而繫於該索引上的關聯就會錯亂!

    三. 無 ID 或主索引字段的資料, 能否與其它資料建立關聯?

    在自然情況下有些資料並不需要 ID 字段 (或是 ID 字段值並無實質意義), 例如: 

    1. 每天例行發出的提醒信息可能並不需要 ID 值, 但是, 當使用者從清單中選擇一筆資料時, 系統如何明確地找到被指定的提醒明細呢?

    2. 展開MPS 是一個批次作業, 其過程中會有許多的記錄臨時被產生或是合併!在每一筆過渡記錄產生時, 並不需要具有編碼規則的 ID 字段, 但是在整合同料號同時段的生產需求時, 如何能夠正確地標記已被合併的數據呢?歸納以上的難題, 我們可以發現需求的核心就是: 能否爲數據庫裏的所有記錄, 賦予一個: (1)簡單, (2)獨一無二, (3)不會改變的"身份識別"?

    How does GUID change the world ?

    GUID 的唯一性完全滿足我們的需求, 因此, 我們可以一個 GUID 字段做爲代理鍵, 以取代自然鍵 (通常爲資料表中"ID" 字段, 或是複合字段組成的主要索引), 並化解實務上遭遇的問題:

    一. GUID 隔離了自然鍵以及關聯的資料表:

    自然鍵是可以被檢視的, 若自然鍵爲ForeignKey 且有對應的關聯資料, 爲了保持資料的一致性, 自然鍵值不應被異動或刪除! 這樣的保護控制大都需要額外的程序代碼去處理!

    代理鍵通常並不具字面上的意涵(例如: GUID), 因此, 在檢視資料時並不會顯現該字段, 所以代理鍵在產生後, 該值並無機會發生改變! 以代理鍵替代自然鍵成爲資料表關聯的主角, 自然鍵相對地成爲類似"備忘" 性質的字段! 由於代理鍵被隱藏而不會被變更, 不論自然鍵如何修改, 根源於代理鍵所形成的數據關聯永遠穩定地存在!

    二. GUID 替代複合字段的自然主鍵:

    當自然主鍵是由多個字段組合而成時, 要撰寫資料關聯的SQL command 就顯得有點煩人! 運用 GUID 字段進行關聯, 可以輕易地使 SQL 化繁爲簡!另外, 當自然鍵由複合字段組成時, 有更多字段被同時使用於資料關聯, 相對地, 需要對字段組合進行更多判斷或是限制變更! 這樣的控制需要付出偏高的代價, 實務上, 也不盡然可以進行控制, 例如: 因爲其它單據明細的增減, 會 "強迫" 部份單據明細自然鍵裏的序號字段遞增/ 遞減!

    若以 GUID 做爲代理鍵擔任資料表的關聯角色, 單據明細的 "序號" 字段因不涉及關聯, 即可依據實務上的需求被變更, 並不需要額外的判斷或控制!

    三. 無自然鍵的資料表由 GUID 代理主鍵的功能:

    在無自然主鍵的資料表建立 GUID 代理鍵後, 每一筆記錄即刻具備可供識別 "身份" 的信息! 即使後來因爲需求變更而必須存取該資料表中特定的記錄時, GUID 代理鍵的存在足以滿足這類的變動 (類似 "防震" 效果)!


The actual usage of GUID

    一. 在多對多的關聯裏替代複合字段以簡化對應:

    如: 傳票分錄的立衝 (傳票明細多對多立衝), 借還款的沖銷 (多對多衝銷), ..... 等, 可由 GUID 代理鍵進行關聯, 即可依 GUID 合併後統計沖銷金額!

    二. 在臨時產生的資料中提供精確的識別:

    如: 有些複雜報表需要額外統計或運算, 當這些運算不需以程序代碼循環處理, 即可以SQL command 直接在該報表的暫存數據表批次運算(其實多數報表均爲如此)!當多人同時檢視相同報表 (檢視條件並不相同), 即可運用 GUID 做爲該暫存資料表中的識別! 每個使用者每次檢視報表即爲一個 Task (TaskGUID), 報表運算後只回傳 TaskGUID 相符的數據!

    幾種高階的開發語言 (包括: .NET, VB, Delphi, PowerBuilder, ....) 均已包裝或是實現呼叫 Windows API 以產生 GUID 字符串的方法了, 所以這個 GUID 值可以由程序代碼自行產生!Microsoft SQLServer 也提供了取得 GUID 字符串的函式 NewID; 還有未公開的 Stored procedure: sp_MSforeachtable, 它可以對數據庫中所有的資料表進行統一的操作!結合 sp_MSforeachtable 與 NewID, 我們可以在幾秒鐘內對所有資料表統一添加名爲 "GUID" 的字段(實例如下), 開始讓 GUID 做爲資料搜尋或關聯的根據!

    /* 先指定要添加 GUID 字段的數據庫後, 直接執行下列語法 */
    sp_MSforeachtable @command1=‘ALTER TABLE ? ADD [GUID] VarChar(36) NOT NULL 
                                               Constraint [?_DF_GUID] DEFAULT (newid()) 
                                               Constraint [?_IX_GUID] UNIQUE NonClustered‘

    What‘s matter with GUID?

    由於做爲索引字段(不論是Clustered Index/ Nonclustered Index) 的GUID 長度爲36 Bytes, 相較於其它的自然鍵或自動編號(整數) 均顯得過長, 使得索引頁可容納的信息較少, 必須搜尋較多的索引頁次才能查詢所需要的結果, 因此, 各個網絡討論區對於 GUID 在效能方面的表現是頗有質疑的!不過, 數據庫系統的效能包括許多因素, 包括: 系統設計理念, 資料表切割, 索引設定, SQL command 撰寫, 內存配置, IO 設備, ..... 等 (排行愈前者影響愈大), 效能調整需要全面的協調與改善, GUID 不會是運行效能的瓶頸肇因!市場上已存在着全面運用 GUID 代理鍵的商用軟件, 被中小企業廣泛採用的 Microsoft.SharePoint 系統也是如此!

    由於運用 GUID 做爲代理鍵, 許多因爲自然鍵直接關聯的難題會因爲 GUID 的隔離而被優雅地化解, 原自然鍵上的複雜控制均可省略, 資料表之間的關聯變得單純, 數據庫系統的運作也更穩定! 


GUID(Global unique identifier)全局唯一標識符,它是由網卡上的標識數字(每個網卡都有唯一的標識號)以及 CPU 時鐘的唯一數字生成的的一個 16 字節的二進制值。
GUID 的格式爲“xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx”,其中每個 x 是 0-9 或 a-f 範圍內的一個十六進制的數字。例如:6F9619FF-8B86-D011-B42D-00C04FC964FF 即爲有效的 GUID 值。
世界上的任何兩臺計算機都不會生成重複的 GUID 值。GUID 主要用於在擁有多個節點、多臺計算機的網絡或系統中,分配必須具有唯一性的標識符。在 Windows 平臺上,GUID 應用非常廣泛:註冊表、類及接口標識、數據庫、甚至自動生成的機器名、目錄名等。
在這次開發 ASP.NET 應用時,我大量使用了類型爲 GUID 的 ID 列作爲各實體表的關鍵字(鍵)。由於其唯一、易產生的特性,給應用程序處理帶來諸多好處。
1、在 SQL Server 中使用 GUID
如果在 SQL Server 的表定義中將列類型指定爲 uniqueidentifier,則列的值就爲 GUID 類型。
SQL Server 中的 NewID() 函數可以產生 GUID 唯一值,使用此函數的幾種方式如下:
1) 作爲列默認值
將 uniqueidentifier 的列的默認值設爲 NewID(),這樣當新行插入表中時,會自動生成此列 GUID 值。

2)使用 T-SQL
在 T-SQL 中使用 NewID()函數,如“INSERT INTO Table(ID,... ) VALUES(NewID(),...)”來生成此列的 GUID 值。
3)提前獲取 GUID 值
由於特殊功能需要,需要預先獲知新行的 ID 值,也可以使用如下 C# 代碼提前獲得 GUID 的值,再存儲到數據庫中:
 SqlCommand cmd = New SqlCommand();
 cmd.CommandText = "SELECT NewID()";
 string rowID = (string) cmd.ExecuteScalar();
 cmd.CommandText = "INSERT INTO Table(ID,...) VALUES(@ID,...)
 cmd.Parameters.Add("@ID",SqlDbType.UniqueIdentifier).Value = new Guid(rowID);
 cmd.ExecuteNoQuery();
uniqueidentifier 值不能進行算術運算,但可以進行(意義不大的)比較操作和 NULL 檢查;它不能象 IDENTITY 列一樣,可以獲知每行的增加時間的先後順序,只能通過增加其它時間或時間戳列來完成此功能。
2、在 .NET 中使用 GUID
GUID 在 .NET 中使用非常廣泛,而且 .NET Framework 提供了專門 Guid 基礎結構。
Guid 結構的常用法包括:
1) Guid.NewGUID()
生成一個新的 GUID 唯一值
2) Guid.ToString()
將 GUID 值轉換成字符串,便於處理
3)構造函數 Guid(string)
由 string 生成 Guid 結構,其中string 可以爲大寫,也可以爲小寫,可以包含兩端的定界符“{}”或“()”,甚至可以省略中間的“-”,Guid 結構的構造函數有很多,其它構造用法並不常用。
同時,爲了適用數據庫中使用 GUID 的需要,.NET Framework 也提供了 SqlGUID 結構,它和 Guid 結構類似,只是兩者對排序(CompareTo)的處理方式不同,SqlGuid 計算值的最後 6 個字節。而 Guid 計算全部 16 個字節,這種差異可能會給 SQL Server 中 uniqueidentifier 列的排序帶來一定影響,當然這種排序意義也不大。
.NET Framework 中可以使用類 GuidConverter 提供將 Guid 結構與各種其他表示形式相互轉換的類型轉換器。

3、GUID 的優缺點
1) 優點
  • 同 IDENTITY 列相比,uniqueidentifier 列可以通過 NewID() 函數提前得知新增加的行 ID,爲應用程序的後續處理提供了很大方便。

  • 便於數據庫移植,其它數據庫中並不一定具有 IDENTITY 列,而 Guid 列可以作爲字符型列轉換到其它數據庫中,同時將應用程序中產生的 GUID 值存入數據庫,它不會對原有數據帶來影響。

  • 便於數據庫初始化,如果應用程序要加載一些初始數據, IDENTITY 列的處理方式就比較麻煩,而 uniqueidentifier 列則無需任何處理,直接用 T-SQL 加載即可。

  • 便於對某些對象或常量進行永久標識,如類的 ClassID,對象的實例標識,UDDI 中的聯繫人、服務接口、tModel標識定義等。
2) 缺點
  • GUID 值較長,不容易記憶和輸入,而且這個值是隨機、無順序的,所以使用時要注意場合,最好不要嘗試用它來作爲你的電子郵件地址 J

  • GUID 的值有 16 個字節,與其它那些諸如 4 字節的整數相比要相對大一些。這意味着如果在數據庫中使用 uniqueidentifier 鍵,可能會帶來兩方面的消極影響:存儲空間增大;索引時間較慢。

綜合來說, GUID 的優點帶來的便利遠超出其缺點帶來的影響,隨着諸如 WebService 等系統互聯與整合技術的不斷髮展,其唯一標識的特性使得其應用越來越廣,在您的應用程序中也應考慮使用它了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章