2011-10-24 36 views
3

我試圖做一個通用處理器發佈基於我的實體類型SYSTEM_AUDIT_SHEET一個JSONJ對象:轉換實體框架對象JSON對象

SYSTEM_AUDIT_SHEET sheet = ctx.SYSTEM_AUDIT_SHEET 
           .Where(s => s.SYSTEM_KEY == system_key_dec) 
           .Select(s => s) 
           .OrderByDescending(s => s.AUDIT_SHEET_VERSION) 
           .First(); 

HttpContext.Current.Response.Write(serializer.Serialize(sheet)); 

,但我得到了以下錯誤:

A circular reference was detected while serializing an object of type 'System.Data.Entity.DynamicProxies.SYSTEM_AUDIT_SHEET_521A7B786A51FC0F83641182DD72C8DFE6C082418D30BBB977B403409A74CE17'.

爲什麼我不能將實體轉換爲JSON?

+0

創建一個新類,類似於要序列化的對象,但沒有循環引用。從表單對象填充該類中的數據並對其進行序列化。由於這種問題,直接序列化實體框架對象是一種不好的做法。 – Birey

+0

重複的問題;答案是「使用JSON.Net」,它有幾個解決方案,這個問題沒有複製/粘貼類。 http://stackoverflow.com/questions/4606232/circular-reference-exception-with-json-serialisation-with-mvc3-and-ef4-ctp5w –

回答

1

您無法將對象轉換爲引用自己的json,因爲這會創建無限長的json字符串。

例如,下面的僞代碼是行不通的,因爲它建立了一個循環引用(狗骨>> >>狗...):

class Dog { 
    private Bone myBone; 
    public Dog() { 
     myBone = new Bone(this); 
    } 
} 

class Bone { 
    private Dog buriedBy; 
    public Bone(Dog d) { 
     buriedBy = d; 
    } 
} 

似乎有一些好的解決方案通過谷歌搜索'json循環參考'。查看前兩個堆棧溢出鏈接。

+2

'Google它'不是一個非常有用的答案。你能提供一個鏈接嗎? –

+0

我提供了一個答案和獲得更多資料的方法。我在搜索頁面上引用了多個鏈接......確實給出特定的Google搜索字詞是提供其他參考資料的最有效方式。 – jtfairbank

+1

以下是需要它們的鏈接:1. [Json和循環引用異常](http://stackoverflow.com/questions/2002940/json-and-circular-reference-exception)2. [EF 4.1 - 代碼首先 - JSON循環引用序列化錯誤](http://stackoverflow.com/questions/5588143/ef-4-1-code-first-json-circular-reference-serialization-error)3. [EF 4.1 + MVC + JSON循環引用異常?](http://stackoverflow.com/questions/6622430/best-solution-for-ef-4-1-mvc-json-circular-reference-exception) –

1

這個問題可能是你的SYSTEM_AUDIT_SHEET要麼包含引用SYSTEM_AUDIT_SHEET類型的實例的屬性,或者它包含一個指向具有指針SYSTEM_AUDIT_SHEET實例對象的屬性。序列化這樣一個指針循環會導致一個永遠不會結束的序列化過程。

您需要將您的SYSTEM_AUDIT_SHEET轉換爲在序列化之前不會(直接或間接)引用自身的類型。你可以創建一個全新的類型,並編寫代碼來實例化你的類型SYSTEM_AUDIT_SHEETAutoMapper可能在這裏派上用場)。但是,我往往會發現,在大多數情況下,很容易,只需使用匿名類型:如果你想使用AutoMapper和假設

SYSTEM_AUDIT_SHEET sheet = /*some sheet*/ 
var json = new { 
    sheet.Id, 
    sheet.RevisionNumber, 
    sheet.Title 
}; 
return serializer.Serialize(json); 

編輯

,你的表看起來像

class SYSTEM_AUDIT_SHEET 
{ 
    public int Id { get; set; } 
    public SYSTEM_AUDIT_SHEET SomeOtherAuditSheet { get;set;} 
    public string Title { get;set;} 
} 

你可以創建一個類型像

class JSON_SYSTEM_AUDIT_SHEET 
{ 
    public int Id { get; set; } 
    public int SomeOtherAuditSheetsId { get;set;} 
    public string Title { get;set;} 
} 

應用程序啓動時(比如說,在的Application_Start)配置AutoMapper:

AutoMapper.Mapper.CreateMap<SYSTEM_AUDIT_SHEET, JSON_SYSTEM_AUDIT_SHEET>() 
    .ForMember(dest => dest.SomeOtherAuditSheetsId, opt => opt.MapFrom(src => src.SomeOtherAuditSheet.Id)); 

IdTitle屬性將直接對面SYSTEM_AUDIT_SHEET被映射到JSON_SYSTEM_AUDIT_SHEET因爲他們有兩種類型相同的名稱。屬性SomeOtherAuditSheetsId需要特殊配置,因爲在源類型中沒有具有該確切名稱的屬性。

當你要轉換SYSTEM_AUDIT_SHEET到JSON_SYSTEM_AUDIT_SHEET你做:

return AutoMapper.Mapper.Map<SYSTEM_AUDIT_SHEET , JSON_SYSTEM_AUDIT_SHEET >(sheet); 

你可能想看看AutoMapper's flattening features

希望這會有所幫助。

+0

是的,但因爲有像30個屬性我不想手動做。我想那是什麼automapper是用於?你能告訴我它是如何使用的嗎? – Johan

+0

+1使用AutoMapper。任何人都知道現有的工具或模板會自動複製POCO嗎? –