奇妙的動態代理:EF中返回的對象爲何序列化失敗

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


    憑着感受,我問「這個對象是普通對象仍是什麼對象」,回覆說「是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最新課程

相關文章
相關標籤/搜索