淺談Linq to Sql 的不足

來源:互聯網
上載者:User
    前兩星期,因為項目的需要,靜下心來讀完了《Pro.LINQ.Language.Integrated.Query.in.Csharp.2008》的 linq to object 和 linq to Sql 部分,希望能將Linq to Sql 應用在我們的項目中。讀完後,頗有些心得,也深感到 Linq to Sql 的不足。

    這裡我不討論Linq的基本文法,也不討論怎麼用 Linq to Sql 來對資料庫做SIUD操作,關於這方面的文章,網上已經有很多了。這裡主要談Linq to Sql的不足之處。

不足1:規則太死,可擴充性少
    這裡說的規則太死,主要指業務層實體與資料庫表的綁定。基本上只能是一個實體物件對應於一個表,而且,對實體物件的要求太多,比如,(1)該實體物件必須要有預設無參構造方法(如果沒有也會編譯通過,但無法運行,因為Linq to Sql是通過反射來構造對象,而且用的是該對象的無參構造方法);(2)該實體的所有實體儲存欄位都不能有readonly關鍵字(反射要對該欄位寫值);(3)如果該實體存在對子物件(“一對多”關係的“多”一方的實體物件)的一個列表,則該列表必須是EntitySet<T>類型;(4)如果該實體有對父物件(“一對多”關係的“一”一方的實體物件)的引用,則該應用類型必須是EntityRef<T>類型,而且還要有相對於父物件主鍵這樣的欄位存在。所有這些規則,註定了業務層實體物件基本沒有辦法自己來手寫以進行自訂,進行擴充。那有人說了,本來就沒讓你手寫,有SqlMetal和可視化設計工具存在,還手寫,吃飽了撐著。我同意這些工具確實非常有用,但是這些工具產生的實體滿足我們業務的需要嗎?因為業務的變化是多樣的,而過多的條條框框卻大大縛束了我們的手腳。

不足2:不支援TimeSpan
    真是不可思議,實體類的TimeSpan欄位怎麼都沒法直接映射到Sql Server的列中去(也許我沒找對方法,若大家有辦法,歡迎告知)。怎麼辦?難道要變通一下。是可以變通,而且變通的辦法很多,但是,這種基本的類型都要變通才能實現,難道說這是一個足夠成熟足夠強大的架構所應該展現給大家看的嗎?

不足3:透明性不夠,使用上有困難
    我在看書之前,曾寫過這樣的代碼,如下:
            using (ProgramConsoleDataContext db = new ProgramConsoleDataContext())
            {
                BaseTask baseTask = new BaseTask()
                {
                    Name = "jhh",
                };

                db.BaseTasks.Attach(baseTask);
                db.SubmitChanges();
            }
    結果運行失敗,當然我現在知道為什麼失敗,但這也暴露了一個問題,就是使用者在使用Linq to Sql時,必須清楚DataContext對象的內部運作方式。看到Table<T>的“InsertOnSubmit”與“DeleteOnSubmit”這樣的方法,就足以說明其封裝性不夠這樣的問題。實際上,“InsertOnSubmit”原來設計的名字叫“Add”,“DeleteOnSubmit”原來的名字叫“Remove”,請問,你是喜歡後面的名字還是前面的名字,是喜歡後面的封裝還是前面的封裝?估計原來Linq to Sql設計團隊的目標是提供一個封裝性更強的架構,但後面因為種種原因沒有實現,於是退而求其次,但怕大家誤解“Add”與“Remove”這樣方法,於是改成現在的名字,以強調“Submit”的概念(純屬個人猜測)。
    DataContext所提供的實體變更跟蹤功能是一大亮點,但使用上感覺不是很方便,也許是我沒找到好的運用模式。我在想,我是該永久儲存該對象的一個引用呢,還是用到一次建一次對象。如果採用第一種方法,那麼我的程式將隨著已耗用時間的增長而Load越來越多的資料,最後,可能整個資料庫都在Load進來;那如果採用第二種方法,那麼我怎麼利用它提供的實體變更跟蹤功能呢?當然,可以使用Table<T>的Attach方法,但我不是每次都知道UpdateMode的方式,而且,要是我要Attach的這個對象是個大對象呢,下面掛了很多的EntitySet呢,我又該怎麼Attach?我思考了很久,沒有找到答案。

不足4:效能問題
    這個就不用說了,通過反射來實現的,當然有損失,也能接受,現在的ORM有不損失效能的嗎?所以,這個可以說是問題,也可以說不是問題,大家都能理解。但是,DataContext的實體變更跟蹤的實現,卻又是以效能、空間來換取的。不信你試試,在DataContext中Retrieve一個實體,然後更改該實體,你看看你的實體構造方法被調用了幾次?是不是兩次?為什嗎?因為Retrieve時一次,更改該實體時又一次,因為DataContext儲存了該實體的原始副本。本來,我聽說,在實體中實現INotifyPropertyChanging與INotifyPropertyChanged這兩個介面後,DataContext就能根據該介面提供的功能來進行實體變更跟蹤,我想,這樣就不會建立一個副本了吧,結果發現還是建了一個副本,這是為什嗎?不知道。

    我還沒有用Linq to Sql做過項目,因此以上的看法可能都不是很成熟。實際上,我想,Linq to Sql本來的定位就不是面向企業級運用的,我們也不要對它要求太多,實際上,簡單就是它最大的美。我認為它適合於做一些比較簡單的、商務邏輯不複雜的項目,但不適合做大的項目,我甚至認為中型的項目也不適合用它來做。目前Ado.net Entity Framework已經bate3了,期待它帶來的Linq to entities能帶給我們驚喜。

    最後,提出一個疑問:ORM真的有大的前景嗎?大規模的項目有用ORM的嗎?什麼時候會有成熟的物件導向的資料庫產品,或者因為關聯式模式在數學上的優美性而永遠不會有呢?

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.