多語言架構下如何正確的使用SQL檢視

孫凱旋發表於2016-07-27

產品的定位

做產品的都知道,是否支援多語言直接影響到產品的定位問題。

如果一個產品週期是一年的話,要完美支援多語言最少也得在加3個月!所需時間和頁面數量、資料庫表的數量和表的資料量成正比。

可以看出代價有多大,我們程式設計師就得和老闆嘮叨,做不得,成本太高。

如果前期不做,等到了後期專案表結構等都要重構,如果使用了大量的檢視對於多語言來說就是惡夢。

 

非資料庫方面的解決方案

請看我上一篇貼子 http://www.cnblogs.com/sunkaixuan/p/5699744.html

 

資料庫表的設計

對於多語言來說最重要的就是清單表的設計, 就拿簡歷來說吧,至少會用到十幾張清單表 (當然你也可以儲存在一張表裡用分類

學歷表:小學、中學、大學、博士 等等 

工作年限表:習實生,1年工作經驗,2年工作經驗等等

...

 

多語言架構清單表的設計誤區

如下圖這種設計是存在嚴重缺陷的,列來存語言難道我多一種語言就要加一列,顯然是不合理的

錯誤方案

 

 

正確的設計方案

 

名稱                      清單ID     語言ID

Primary education   1            1

小學                       1            2

middle school         2            1

初中                       2            2

資料結構應該是這樣的至少,相同的東西是一樣的ID,名稱不一樣而已,產品架構千萬不要用列儲存。

 

這種表架構又會出一個問題

當使用語言ID來作為篩選時,就會遇到一個很大的問題,沒錯那就是檢視的JOIN問題,如果我在檢視裡面寫

人員表 JOIN 學歷表  ON   學歷表.ID=人員表.學歷ID  AND  學歷表.語言ID=幾 

沒法寫了對不,如果我在檢視裡寫了1那就意味著我查出來的清單都只會是一種語言(語言ID為1的那個語言)

 

檢視的作用

檢視相當於虛擬表,可以方便的複用,檢視還可以套檢視,並且檢視在索引合理的情況下,比單表查詢還要快。 (索引覆蓋就是一個很好的例子)

 

那怎麼辦呢?SqlSugar ORM已經為我們做好這一切

隨著ORM效能瓶頸的提升,都玩會了EMIT 快取這套,甚至拉姆達TO SQL都有開源專案 大大降低了ORM的門檻,SqlSugar也是拉姆達解析加EMIT玩的最早的ORM之一。

SqlSugar是為通用框架搭建而生,擁有了一定量的使用者,在6600萬高併發的測試中也得到了使用者的好評。

雖然也有很多朋友抱怨問題,大致會有兩個問題 實體轉換報錯,其實是欄位型別不配引起的或者更改了表結構沒有把.NET例項重啟因為有快取的原因。

我不能保證我的程式碼寫的多優雅,但能保證我寫的程式碼都能看懂。我寧可寫IF ELSE也不會寫讓我腦子在轉一圈的程式碼,我不會因為我一天能解決的問題去套一個使我花2天以上解決問題的設計模式,合理封裝便可,沒有過度設計。

 

SqlSugar在很多細節上都做過處理,比如執行緒安全、事務隔離等引數

 

使用SqlSugar ORM解決檢視問題

 

1、我們就把檢視語言ID設為1 (1為預設語言)
人員表 JOIN 學歷表  ON   學歷表.ID=人員表.學歷ID  AND  學歷表.語言ID=1

2、我們可以使用 LanguageHelper.UpdateView(db.Language, db); 幫我們生成其它語言的檢視,只要使用在Application_Start執行一次便可以,當檢視發生變化也需要在調一次或者重啟程式

只要檢視原始碼中包含LanguageId=1的所有檢視都會建立出新的檢視並且把
LanguageId=1替換成你想要的ID


3、他會根據引數生成一個新的檢視 原檢視名_$_
EN ,新的檢視和原檢視一樣只是名稱和語言的值發生了變化
人員表 JOIN 學歷表  ON   學歷表.ID=人員表.學歷ID  AND  學歷表.語言ID=2

4、var list=db.Qureyable<原檢視名>().ToList()
ORM會自動識別新的檢視進行查詢,生成的SQL如下 SELECT * FROM 新檢視名


下面是具體程式碼:

 

  using (SqlSugarClient db = SugarDao.GetInstance())//開啟資料庫連線
            {
                db.Language = new PubModel.Language()
                {
                     LanguageValue=2,//多語言的值一般從COOKIES或SESSION取
                     Suffix="en"//多語言字尾同上
                };
                //給上面賦值後下面的程就可以使用了
                int lanId=db.Language.LanguageValue;
                var list = db.Queryable<LanguageTest>().Where(it => it.LanguageId == lanId).ToList(); 


                /****************************多語言檢視才是最大的問題***********************************/


                //注意檢視裡裡怎麼辦呢?檢視裡面的JOIN用到語言表怎麼處理呢
                //我們就寫一個簡單的檢視作為例子,程式碼如下
                /*create view V_LanguageTest
                    as
                    select * from LanguageTest where LanguageId=1
                 */

                //下面這程式碼寫到 application_start  不需要重複執行
                LanguageHelper.UpdateView(db.Language, db);
                //執行完上面的程式碼會建立把所有帶LanguageId=1的檢視全部生成其它語言的檢視
                //現在資料庫就有了 V_LanguageTest_$_en

                // V_LanguageTest_$_en結構如下
                /*create view V_LanguageTest_$_en
                 as
                 select * from LanguageTest where LanguageId=2
                 */

                //V_LanguageTest__$_en 是我SqlSugar自動幫你建立的 當檢視發生變化需要重新執行 LanguageHelper.UpdateView(db.Language, db);

                var list2=db.Queryable<V_LanguageTest>().ToList();
                //生成的Sql等於 select * from V_LanguageTest_$_en 

                 
                db.Language.LanguageValue = 1;//我們在把LanguageValue改成1
                db.Language.Suffix = null;//字尾清空
                var list3 = db.Queryable<V_LanguageTest>().ToList();

                //生成的Sql等於 select * from V_LanguageTest

                //注意當 Suffix為null時使用的原始檢視

                //自定義檢視替換規則請看下面兩個引數
               //db.Language.ReplaceViewStringKey 預設值為LanguageId=1
               //db.Language.ReplaceViewStringValue 預設值為LanguageId = {0}
                
            }

 

SqlSugar學習下載地址:

http://www.cnblogs.com/sunkaixuan/p/5654695.html

相關文章