奇妙的動態代理:EF中返回的對象為什么序列化失敗


    今天有如鵬的學生遇到一個問題:把一個對象保存到Session中(進程外Session)后,Web服務器重啟,當從Session讀取這個對象的時候報錯,提示是一個“T_Users”后面跟着一大串數字的類型,不是“T_Users”類型。


    憑着感覺,我問“這個對象是普通對象還是什么對象”,回復說“是Entity Framework返回的對象”,瞬間我知道了:是延遲加載造成的。
下面寫個程序驗證一下。


    數據庫里建立兩張表:一張T_Persons表,一張T_Dogs表,T_Dogs表中有一個MasterId字段是指向T_Persons的外鍵,表示“狗的主人是誰”。
    然后創建數據庫的Entity。然后編寫下面的代碼:

abcEntities e = new abcEntities();
T_Persons p = e.T_Dogs.First().T_Persons;
Type t = p.GetType();
Console.WriteLine("對象類型:"+t);

  

    第二行代碼的意思很顯然是:獲得T_Dogs中第一個對象的主人對象,然后第三行獲得的是對象的類型,我們驚奇的發現打印結果是:System.Data.Entity.DynamicProxies.T_Persons_A2C5F62323A22039FDCBEB40BD……


    很奇怪,不應該是T_Persons類的對象嗎,怎么是這么一個怪玩意。


    這就涉及到“延遲加載(LazyLoading)”的原理了。對於需要延遲加載的對象,EF會動態生成一個實體類型的子類,這個子類是一個“動態代理(DynamicProxy)”類,這個類會進行延遲加載的處理。所以我們拿到的對象不直接是T_Persons類的對象,而是“動態代理(DynamicProxy)”類的子類,當然由於這個類是T_Persons的子類,所以“T_Persons p = e.T_Dogs.First().T_Persons”這樣用父類的變量指向它也是可以的。多態經常偷偷幫我們做很多奇妙的事情。

    由於這個對象是動態產生的類的對象,當程序重啟之后,產生的“動態代理(DynamicProxy)”類和之前的“動態代理(DynamicProxy)”類就是兩個類了。所以就會反序列化失敗了。


    很多ORM框架中延遲加載都是使用動態代理來實現的,比如Java中的Hibernate或者.Net的移植版NHibernate。

 

如鵬網.Net培訓班正在報名,有網絡的地方就可以參加如鵬網的學習,學完就能高薪就業,點擊此處了解

 

    三年前只要懂“三層架構”就可以說“精通分層架構”;現在則需要懂IOC(AutoFac等)、CodeFirst、lambda、DTO等才值錢;

    三年前只要會SQLServer就可以說自己“精通數據庫開發”;現在則需還需要掌握MySQL等開源數據庫才能說是“.Net開源”時代的程序員;

    三年前只要會進行用戶上傳內容的安全性處理即可;現在則需要熟悉雲存儲、CDN等才能在雲計算時代游刃有余;

    三年前只要掌握Lucene.Net就會說自己“熟悉站內搜索引擎開發”;現在大家都用ElasticSearch了,你還用Lucene.Net就太老土了;

    三年前發郵件還是用SmtpClient;現在做大型網站發郵件必須用雲郵件引擎;

    三年前緩存就是Context.Cache;現在則是Redis、Memcached的天下;

    如鵬網再次引領.Net社區技術潮流!點擊此處了解如鵬網.Net最新課程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2026 CODEPRJ.COM