是否有人使用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