2013-11-25 33 views
0

我已經閱讀了關於實體框架生成對象的WCF序列化的幾個問題/文章,但是我發現的所有解決方案都涉及到啓用急切加載,這正是我嘗試不做的事情。如何阻止WCF序列化的實體框架類嘗試延遲加載?

我實際上得到了與此處提到的The ObjectContext instance has been disposed - Winforms Entity Framework相同的錯誤,區別在於我使用的是Silverlight應用程序中的WCF服務。

我有一個表User_Notifications有一個表的外鍵User_Info。 (如果我沒有正確使用術語,單個User_Info可指向許多User_Notifications)。我正在使用實體框架4,它爲這兩者創建了一個類。我有一個WCF調用返回:

return DBEntity.User_Notifications.Where(w => w.UserGUID == UserGuid && w.IsDismissed == false).ToArray(); 

這給了我所有的User_Notifications,我需要,但我得到的ObjectContext的實例已在客戶端上,它看起來像一個嘗試加載相關配置錯誤User_Info類。我不希望User_Info數據,但我希望它保持空或什麼,我不需要它顯示通知。

那麼,如何傳遞我的實體對象而無需傳遞關聯對象呢?

我的老闆說這只是'我們不需要數據庫中的外鍵'的另一個原因,我真的不想走這條路。

+2

聽起來像你的老闆應該堅持與編程無關的事情。 – Matthew

+0

@Matthew我的老闆是框架開發人員,並且一直在過去10年。幾個月前,我向他展示了這個叫做.net字典的很酷的新東西。 – cost

+0

可能有用:http:// geekswithblogs。net/danemorgridge/archive/2010/05/04/entity-framework-4-wcf-amp-lazy-loading-tip.aspx(禁用延遲加載) – Matthew

回答

0

對於它的價值,堅持不要在數據庫中有外鍵。他們應該在那裏,期間。

就你的問題而言......聽起來你想要返回一個User_Notifications集合,其中User_Info對象在初始查詢中未加載,對吧?默認情況下,對錶的查詢不應該急於加載關聯的對象。

在服務功能,只是做:

return (from n in DBEntity.User_Notifications 
     where n.UserGUID == UserGuid && n.IsDismissed == false 
     select n).ToArray(); 

如果你發現你需要在客戶端的USER_INFO對象,然後只需更改上面:

return (from n in DBEntity.User_Notifications.Include("User_Info") 
.... 
+1

我認爲問題在於導航屬性被WCF中的序列化機制延遲加載。 – Matthew

+0

@Mthethew是的,這是問題。我的客戶正在嘗試加載關聯的'User_Info'對象,這不在那裏。 – cost

+0

您可以配置您的數據庫模型以禁用實體模型設計器中的延遲加載(我總是這樣做)。如果您點擊背景,該選項位於屬性窗口中。 WCF不應該延遲加載任何東西。 –

0

我的建議不要直接通過WCF公開您的EF實體,而是通過您的服務公開DTO。

這有兩個好處,首先,你正在處理真正的POCO(不是延遲加載代理),它們沒有持久化的具體細節。第二個是你只公開消費者實際需要的東西,這意味着你可以改變底層的實現而不強制客戶端重新編譯,而且你不必將整個數據模型公開給他們。

在你的榜樣,你可以有:

// I'm not a fan of the Dto suffix, but it makes this example easier 
public class UserNotificationDto 
{ 
    // the properties you want to expose through WCF 
    public Guid UserGuid { get; set; } 
    public string Message { get; set; } 
    // ...   
} 

// your service method 
IEnumerable<UserNotificationDto> GetNotifications(Guid userGuid) 
{ 
    using (var ctx = new Context()) 
    { 
     return ctx.User_Notifications 
      .Where(x => !x.IsDismissed && x.UserGuid == userGuid) 
      .Select(
       x => new UserNotificationDto { 
        UserGuid = x.UserGuid, 
        Message = x.Message 
       } 
      ).ToList(); 
    } 
} 

您可以使用automapper使EF實體和你更容易的DTO之間的轉換,但是這僅僅是一個人爲的例子。

+0

我會同意這是更好的方式來做到這一點,但在這種情況下,歸結起來我有很多代碼要寫,並且要做一個很短的截止日期(爲什麼我要在週日晚上工作我是一名MF程序員)。實體對象本身在某些情況下是暴露的,因爲它允許客戶端進行更改,然後將它們發送回Web服務以保存更改。這是不理想的,但至少這些Web服務將不會被任何東西調用,除了我在這裏寫的東西(外部Web服務像你描述的那樣工作) – cost

+0

我一直在做你喜歡的東西,但它是花太長的時間來編碼一切。這樣的變化。最後,我們都是最後期限的奴隸。但是,嘿,至少我讓框架開發人員讓我最後添加一些外鍵到數據庫中。 – cost

+0

也許你最好的選擇是裝飾你不想序列化的屬性。 'IgnoreDataMember'屬性:http://msdn.microsoft.com/zh-CN/library/system.runtime.serialization.ignoredatamemberattribute%28v=vs.110%29.aspx – Matthew

相關問題