遇到EF使用Oracle Synonym問題,查了資料做了實驗,整理筆記如後。
先說我們在Oracle使用Synonym(別名,有人翻成「同義詞」,我覺得別名順口)的情境:例如人事系統使用"HR"帳號登入Oracle並在自己的HR Schema建立資料表並擁有HR Schema所有資料表的讀寫權限。之後ERP系統要讀存HR Schema下的員工基本資料,當然不能直接用HR帳號密碼連Oracle,而會另開HRQRY之類的帳號,再授與其HR.Employee資料表的讀取權限。這種場景在SQL Server也很常見,只需連線字串改用HRQRY帳號登入,Initial Catalog改指向HR資料庫,用SELECT * FROM Employee就能查到資料。Oracle的Schema概念有點不同,沒法在連線字串用Initial Catalog指定Schema,HRQRY要存取HR下的資料表,得寫成SELECT * FROM HR.Employee。這樣做有兩個缺點,一是每次動用Table時都要加上"HR."挺囉嗦,二是在程式碼寫死了Schema名稱,一旦Schema名稱調整將有改不完的程式。簡便的解決之道是為HR.Employee建立Synonym:
CREATE PUBLIC SYNONYM Employee FOR HR.Employee;
如此,以HRQRY登入也能用SELECT * FROM Employee查詢HR.Employee,如要改由其他Schema讀取Employee,只需重設Synonym,不必改程式。
不過這個做法搬到Entity Framework會遇到一點小挑戰!在Visual Studio建立EF模型時,Entity Data Model Wizard/Choose Your Database Objects(操作畫面請參考舊文) 看不到任何Synonym資料表,換句話說,我們無法使用HRQRY帳號為Synonym資料表建立資料模型!
爬文找到CodePlex EF專案的一則討論,開發團隊基於應用需求不多的理由,未將Synonym納入Entity Data Model Wizard的找尋範圍,這就是操作介面看不到Synonym資料表、檢視、Stored Procedure的原因。
要解決問題,有兩個選擇:
- 開發階段以原帳號(HR)連線資料建立資料模型,測試及上線時再改用HRQRY。
- 如果能接受Code First開發模式(延伸閱讀),OnModelCreating()事件允許指定Schema名稱,如此連Synonym都不需建立。
我們目前開發上已習慣EDMX的視覺化呈現,暫時沒有轉往Code First的打算,故選擇第一種做法。而依據實測,先用HR建好模型,只要Synonym名稱齊全,與原資料表名稱一致且權限有開,連線字串的登入帳號由HR換成HRQRY即可無縫接軌,不需更動任何程式碼,還算方便。
爬文期間還查到一篇Synonym名稱與原資料表不同,如何修改EDMX配合的Hacking技巧,一併記下備忘。