如何序列化實體框架對象爲JavaScript對象(JSON)?我嘗試使用JSON.NET,但當我嘗試序列化它時,出現以下異常。使用Json.Net序列化實體框架對象
例外:Newtonsoft.Json.JsonSerializationException,消息=「自參照循環」
亞太區首席技術官Matt
如何序列化實體框架對象爲JavaScript對象(JSON)?我嘗試使用JSON.NET,但當我嘗試序列化它時,出現以下異常。使用Json.Net序列化實體框架對象
例外:Newtonsoft.Json.JsonSerializationException,消息=「自參照循環」
亞太區首席技術官Matt
這聽起來像您有與原始DataContract串行大致相同的問題,關於循環引用。雖然相互引用的對象與內存中的對象圖相當常見,但如果序列化程序沒有專門說明它,則此類循環引用在序列化時不可避免地會導致無限遞歸。在通用的非二進制序列化格式中處理循環引用的標準(如果有的話)很少(XML和JSON是最常見的兩種)。
Microsoft解決了.NET 3.5中DataContract序列化程序的循環問題SP1通過使用xml中的引用語義。據我所知,JSON不存在這種情況,這可能是JSON.NET妨礙你序列化對象圖的原因。
我會確保你的對象圖中只有引用是可單向導航的,而不是兩種方式(即僅從父到子,不從子到父)。那些父/子和子/父是循環引用的最常見類型。也可能是一個較低級的孩子最終引用圖的根,導致創建一個間接的循環圖(然而,這些往往不如父/子循環常見)。
一旦您可以消除對象圖中的任何循環引用,您應該能夠序列化。
我有這個問題,並通過將Newtonsoft.Json.JsonIgnoreAttribute添加到導致該循環的屬性來解決它。顯然,該屬性不會被序列化。爲了解決這個問題,我通常會在我的實體中使用外部引用ID和外部類。我意識到這不是直觀的(或超級好的OO),但它是Julia Lerman在她的書「編程實體框架:代碼優先」中推薦的方式。我發現它有助於消除Entity Framework中的幾個問題。
public class SomeEntity
{
[JsonIgnore]
public ForeignEntity SomeForeignEntity {get;set;}
public Guid ForeignEntityId {get;set;}
}
更新:我忘了說我還需要上的DbContext禁用代理,像這樣:
dataContext.Configuration.ProxyCreationEnabled = false;
如果你正在寫一個服務代碼(這似乎很可能,如果您序列化) ,那麼這可能不是問題,但是當代理創建被禁用時,你會失去一些東西。看到這裏:http://www.sellsbrothers.com/posts/Details/12665瞭解更多詳情。
我使用的MS網絡API,所以我只是禁用代理創作時,我建我的控制器:
public class MailingApiController : ApiController
{
public MailingApiController()
{
PreventDeepSerialization();
}
private static void PreventDeepSerialization()
{
var dataContext = Injector.Get<IIntertwyneDbContext>();
dataContext.Configuration.ProxyCreationEnabled = false;
}
....
爲了解決這個問題我將我的實體基於POCO的Code First。爲此,請在您的edmx窗口中右鍵單擊並選擇:
添加代碼生成項>代碼選項卡> EF POCO實體生成器。
請注意,如果您沒有看到它,您可能需要使用nuget安裝它。
但是,在運行時,EF會將代理類添加到這些對象用於跟蹤目的,但它們往往會搞亂序列化過程。爲了防止這種情況,我們可以簡單地設置ProxyCreationEnabled爲false如下:
var context = new YourEntities();
context.Configuration.ProxyCreationEnabled = false;
var results = context.YourEntity.Take(100).ToList();
然後,您可以安全地通過省略默認參考循環如下返回JSON.NET串行數據:
return JsonConvert.SerializeObject(results, Formatting.Indented,
new jsonSerializerSettings {
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
謝謝您的回答。我不想消除對象圖中的任何循環引用,因爲我不完全確定如何執行此操作,以及進行此更改會產生什麼影響。相反,我創建普通的簡單對象,並使用實體框架對象填充這些對象,然後序列化普通對象,它工作正常。 – Hitesh 2009-06-24 22:42:27