是否有人使用JSON.NET與nHibernate?我注意到當我嘗試使用子集合加載類時出現錯誤。JSON.NET和nHibernate延遲加載集合
回答
你是否得到一個循環依賴性錯誤?你如何忽略序列化的對象?
由於延遲加載會生成代理對象,因此您的類成員擁有的任何屬性都將丟失。我遇到了與Newtonsoft JSON序列化程序相同的問題,因爲代理對象不再具有[JsonIgnore]屬性。
你可能會想急於負荷大部分對象,以便它可以被序列化:
ICriteria ic = _session.CreateCriteria(typeof(Person));
ic.Add(Restrictions.Eq("Id", id));
if (fetchEager)
{
ic.SetFetchMode("Person", FetchMode.Eager);
}
一個很好的方式做,這是一個布爾添加到構造(布爾isFetchEager)數據的提供者方法。
我使用NHibernate和Json.NET,並注意到我在序列化對象中出現莫名其妙的「__interceptors」屬性。谷歌搜索由Lee Henson翻譯成了this excellent solution,我修改瞭如下的Json.NET 3.5 Release 5。
public class NHibernateContractResolver : DefaultContractResolver
{
private static readonly MemberInfo[] NHibernateProxyInterfaceMembers = typeof(INHibernateProxy).GetMembers();
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
var members = base.GetSerializableMembers(objectType);
members.RemoveAll(memberInfo =>
(IsMemberPartOfNHibernateProxyInterface(memberInfo)) ||
(IsMemberDynamicProxyMixin(memberInfo)) ||
(IsMemberMarkedWithIgnoreAttribute(memberInfo, objectType)) ||
(IsMemberInheritedFromProxySuperclass(memberInfo, objectType)));
var actualMemberInfos = new List<MemberInfo>();
foreach (var memberInfo in members)
{
var infos = memberInfo.DeclaringType.BaseType.GetMember(memberInfo.Name);
actualMemberInfos.Add(infos.Length == 0 ? memberInfo : infos[0]);
}
return actualMemberInfos;
}
private static bool IsMemberDynamicProxyMixin(MemberInfo memberInfo)
{
return memberInfo.Name == "__interceptors";
}
private static bool IsMemberInheritedFromProxySuperclass(MemberInfo memberInfo, Type objectType)
{
return memberInfo.DeclaringType.Assembly == typeof(INHibernateProxy).Assembly;
}
private static bool IsMemberMarkedWithIgnoreAttribute(MemberInfo memberInfo, Type objectType)
{
var infos = typeof(INHibernateProxy).IsAssignableFrom(objectType)
? objectType.BaseType.GetMember(memberInfo.Name)
: objectType.GetMember(memberInfo.Name);
return infos[0].GetCustomAttributes(typeof(JsonIgnoreAttribute), true).Length > 0;
}
private static bool IsMemberPartOfNHibernateProxyInterface(MemberInfo memberInfo)
{
return Array.Exists(NHibernateProxyInterfaceMembers, mi => memberInfo.Name == mi.Name);
}
}
要使用它,只是把一個實例在JsonSerializer的ContractResolver財產。通過將ReferenceLoopHandling屬性設置爲ReferenceLoopHandling.Ignore可以解決由jishi記錄的循環依賴關係問題。下面是可以用於使用Json.Net
public static void SerializeToJsonFile<T>(this T itemToSerialize, string filePath)
{
using (StreamWriter streamWriter = new StreamWriter(filePath))
{
using (JsonWriter jsonWriter = new JsonTextWriter(streamWriter))
{
jsonWriter.Formatting = Formatting.Indented;
JsonSerializer serializer = new JsonSerializer
{
NullValueHandling = NullValueHandling.Ignore,
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
ContractResolver = new NHibernateContractResolver(),
};
serializer.Serialize(jsonWriter, itemToSerialize);
}
}
}
我們有這個確切的問題,這是解決了這裏的靈感來自Handcraftsman的響應對象序列擴展方法。
問題出在JSON.NET對如何序列化NHibernate的代理類感到困惑。解決方案:序列化代理實例,如其基類。
的Handcraftsman的代碼的簡化版本是這樣的:
public class NHibernateContractResolver : DefaultContractResolver {
protected override List<MemberInfo> GetSerializableMembers(Type objectType) {
if (typeof(INHibernateProxy).IsAssignableFrom(objectType)) {
return base.GetSerializableMembers(objectType.BaseType);
} else {
return base.GetSerializableMembers(objectType);
}
}
}
恕我直言,這個代碼有仍然依靠關於自定義屬性,等等JSON.NET的默認行爲的優勢(和代碼是很多短!)。
它這樣使用
var serializer = new JsonSerializer{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore,
ContractResolver = new NHibernateContractResolver()
};
StringWriter stringWriter = new StringWriter();
JsonWriter jsonWriter = new Newtonsoft.Json.JsonTextWriter(stringWriter);
serializer.Serialize(jsonWriter, objectToSerialize);
string serializedObject = stringWriter.ToString();
注:此代碼編寫,並與NHibernate 2.1使用。正如一些評論者指出的那樣,NHibernate的後期版本並不適用,你將不得不做一些調整。我會嘗試更新代碼,如果我必須使用NHibernate的更高版本來完成。
我面臨同樣的問題,所以我試圖使用@ Liedman的代碼,但GetSerializableMembers()
從未被稱爲代理引用。 我發現了另一個方法重寫:
public class NHibernateContractResolver : DefaultContractResolver
{
protected override JsonContract CreateContract(Type objectType)
{
if (typeof(NHibernate.Proxy.INHibernateProxy).IsAssignableFrom(objectType))
return base.CreateContract(objectType.BaseType);
else
return base.CreateContract(objectType);
}
}
我會說這在我看來是一個設計問題。由於NH與所有數據庫連接,中間有代理,所以它不利於應用程序直接序列化它們的透明性(正如你可以看到的,Json.NET根本不喜歡它們)。
你不應該序列化實體本身,但你應該將它們轉換成「視圖」對象或POCO或DTO對象(無論你想調用它們),然後將它們序列化。
不同之處在於,雖然NH實體可能具有代理,惰性屬性等。查看對象是隻有基本類型的簡單對象,默認情況下它們是可序列化的。
如何管理FK? 我個人的原則是:
實體一級:Person類和關聯
查看水平性別類:與GenderId和GenderName性個人檢視。
這意味着在轉換爲視圖對象時需要將屬性擴展爲基元。這樣,你的json對象也更簡單,更容易處理。
當您需要將更改推送到數據庫時,我使用AutoMapper並執行一個ValueResolver類,它可以將您的新Guid轉換爲Gender對象。
更新:檢查http://blog.andrewawhitaker.com/blog/2014/06/19/queryover-series-part-4-transforming/獲取NH中直接獲取視圖(AliasToBean)的方法。這將會對數據庫方面起到推動作用。
- 1. Automapper和NHibernate延遲加載
- 2. nhibernate延遲加載
- 3. Hibernate延遲加載的集合和PropertyChangeSupport
- 4. Silverlight:從nHibernate延遲加載
- 5. NHibernate:延遲加載IUserType
- 6. 尋呼通過延遲加載集合與NHibernate
- 7. NHibernate會話管理和延遲加載
- 8. 繼承和延遲加載NHibernate的
- 9. REST,Json和NHibernate延遲加載
- 10. wcf序列化和nhibernate延遲加載
- 11. NHibernate延遲加載和對象比較
- 12. 流利NHibernate和延遲加載
- 13. nhibernate延遲加載和遞歸保存
- 14. 如何延遲加載嵌套集合?
- 15. ToFuture的延遲加載子集合
- 16. Spring.Net的延遲加載集合
- 17. JPA自動加載延遲集合
- 18. 加載延遲集合在@Transactional方法
- 19. 使用JPA/EclipseLink延遲加載集合
- 20. 延遲加載嵌套集
- 21. IRepository聚合和延遲加載
- 22. NHibernate的延遲加載錯誤
- 23. NHibernate的延遲加載與Ignore.NotFound
- 24. NHibernate延遲加載 - 會話關閉後
- 25. NHibernate的延遲加載問題
- 26. NHibernate的延遲加載行爲
- 27. 防止nHibernate中的延遲加載
- 28. Nhibernate延遲加載一組不工作
- 29. 延遲加載延遲
- 30. 休眠中的延遲加載和集合
可否請您發佈有關您所看到的錯誤的詳細信息? – 2008-11-13 20:30:10
我正在'方法或操作未執行'。並且Liedman的修復爲我工作。 – 2011-10-14 14:51:19