5

我想輸出一個使用DataContractJsonSerializer類的json格式的對象列表,但我一直運行到下面的錯誤。DataContractResolver/KnownType問題當自定義類包含另一個自定義類

Type 'Castle.Proxies.JokeCategoryProxy' with data contract name 
'JokeCategoryProxy:http://schemas.datacontract.org/2004/07/Castle.Proxies' 
is not expected. Consider using a DataContractResolver or add any types not 
known statically to the list of known types - for example, by using the 
KnownTypeAttribute attribute or by adding them to the list of known 
types passed to DataContractSerializer. 

我知道這已被回答之前,但它似乎只發生在我的對象有一個屬性是另一個自定義對象。

[DataContract] 
[KnownType(typeof(ModelBase<int>))] 
public class Joke : ModelBase<int> 
{ 
    [DataMember] 
    public virtual string JokeText { get; set; } 

    [DataMember] 
    public virtual JokeCategory JokeCategory { get; set; } 
} 

[DataContract] 
[KnownType(typeof(ModelBase<int>))] 
public class JokeCategory : ModelBase<int> 
{ 
    [DataMember] 
    public virtual string Name { get; set; } 
} 

正如你所看到的笑話模型包含一個笑話類對象,如果我刪除的笑話範疇,只是有一個int(JokeCategoryId)錯誤消失,雖然一個解決方案,而不是一個理想的,因爲我想使分類可用而不必再次查詢。

下面是我使用生成JSON

public static ContentResult JsonResponse<TReturnType>(this Controller controller, TReturnType data) 
    { 
     using (var oStream = new System.IO.MemoryStream()) 
     { 
      new DataContractJsonSerializer(typeof(TReturnType)).WriteObject(oStream, data); 

      return new ContentResult 
      { 
       ContentType = "application/json", 
       Content = Encoding.UTF8.GetString(oStream.ToArray()), 
       ContentEncoding = Encoding.UTF8 
      }; 
     } 
    } 

什麼混淆我最深的是,錯誤引用Castle.Proxies.JokeCategoryProxy(誰知道這個來自?)

代碼

有什麼建議嗎?

回答

5

nHibernate假定您的所有屬性(除非另有指定)都是延遲加載的。
這意味着,就你而言,只要你拉動你的Joke對象,JokeCategory就不會從數據庫中拉出;相反,動態生成「代理」。
您首次訪問該屬性時,nHibernate知道將其從數據庫中提取出來。 (這是nHib的延遲加載是如何工作的)

所以基本上是怎麼回事的是,你希望你的JokeCategoryJokeCategory類型的,但因爲它是不是真的initialized-它Proxy...類型。

(這只是一個簡要的解釋;谷歌更多的nHib一些和它是如何工作,以瞭解更多,您還可以檢查出summer of nhibernate爲一個偉大的介紹了這個ORM)。

而且,你的問題:你有幾個選擇這裏:

  1. 配置您類別屬性作爲非偷懶,這將迫使NHibernate的與正確的對象類型來初始化它

  2. (更理想,在我看來)做n ot序列化您的Model實體;取而代之的是構建某種DTO,它可以容納你的表示層需要的任何信息。
    這樣,您的演示文稿不需要受域模型更改影響,反之亦然。
    也可以在DTO中保存所有必要的信息,即使它涉及多個Model實體。

例如:

public class JokeDTO 
    { 
     public int JokeId; 
     /*more Joke properties*/ 
     public int JokeCategoryId; 
     public string JokeCategoryName; 
     /*etc, etc..*/ 
    } 
+0

非常有用的東西sJhonny。目前我不會進入DTOs,但我會記住它們以備未來發展。在流暢的nhibernate映射文件中使用.Not.LazyLoad()可以完美地解決即時問題。非常感謝你。 – JConstantine