Nhibernate问题三则
1,nhibernate升级到3.2版本后使用odt获取oracle数据时传入的参数需要是skip的参数加上pagesize才行,而在3.1里没有这个问题
2,linq2nhibernate暂时不支持子查询中有group的语句,方式是将子查询返回list再使用contains
3,Query specified join fetching, but the owner of the fetched association was not present in the select list,在query后使用Fetch获取关联对象时如果提示以上错误请将hbm中的文件修改中的fetech修改为select,修改后调用count时也会保存,请再调用fetch调用count方法
4,关于nhibernate对象中lazyload的属性无法进行json转换的问题,参考这个链接实现对延迟加载对象的剔除,但是如果要json化的对象是另一个对象的属性(例如post对象的readers属性),在序列化的时候由于readers属性是延迟加载的实际的类是prxoy类还需要进行转换成实际的类,请使用下面的代码:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using NHibernate; using NHibernate.Metadata; using NHibernate.Proxy; namespace APSP.Common { public static class NHibernateProxyUtils { /// <summary> /// Force initialization of a proxy or persistent collection. /// </summary> /// <param name="persistentObject">a persistable object, proxy, persistent collection or null</param> /// <exception cref="HibernateException">if we can't initialize the proxy at this time, eg. the Session was closed</exception> public static T Unproxy<T>(this T persistentObject) { var proxy = persistentObject as INHibernateProxy; if (proxy != null) return (T)proxy.HibernateLazyInitializer.GetImplementation(); return persistentObject; } /// <summary> /// Gets the underlying class type of a persistent object that may be proxied /// </summary> public static Type GetUnproxiedType<T>(this T persistentObject) { var proxy = persistentObject as INHibernateProxy; if (proxy != null) return proxy.HibernateLazyInitializer.PersistentClass; return persistentObject.GetType(); } /// <summary> /// Force initialzation of a possibly proxied object tree up to the maxDepth. /// Once the maxDepth is reached, entity properties will be replaced with /// placeholder objects having only the identifier property populated. /// </summary> public static T UnproxyObjectTree<T>(this T persistentObject, ISessionFactory sessionFactory, int maxDepth) { // Determine persistent type of the object var persistentType = persistentObject.GetUnproxiedType(); var classMetadata = sessionFactory.GetClassMetadata(persistentType); // If we've already reached the max depth, we will return a placeholder object if (maxDepth < 0) return CreatePlaceholder(persistentObject, persistentType, classMetadata); // Now lets go ahead and make sure everything is unproxied var unproxiedObject = persistentObject.Unproxy(); // Iterate through each property and unproxy entity types for (int i = 0; i < classMetadata.PropertyTypes.Length; i++) { var nhType = classMetadata.PropertyTypes[i]; var propertyName = classMetadata.PropertyNames[i]; var propertyInfo = persistentType.GetProperty(propertyName); // Unproxy of collections is not currently supported. We set the collection property to null. if (nhType.IsCollectionType) { propertyInfo.SetValue(unproxiedObject, null, null); continue; } if (nhType.IsEntityType) { var propertyValue = propertyInfo.GetValue(unproxiedObject, null); if (propertyValue == null) continue; propertyInfo.SetValue( unproxiedObject, propertyValue.UnproxyObjectTree(sessionFactory, maxDepth - 1), null ); } } return unproxiedObject; } /// <summary> /// Return an empty placeholder object with the Identifier set. We can safely access the identifier /// property without the object being initialized. /// </summary> private static T CreatePlaceholder<T>(T persistentObject, Type persistentType, IClassMetadata classMetadata) { var placeholderObject = (T)Activator.CreateInstance(persistentType); if (classMetadata.HasIdentifierProperty) { var identifier = classMetadata.GetIdentifier(persistentObject, EntityMode.Poco); classMetadata.SetIdentifier(placeholderObject, identifier, EntityMode.Poco); } return placeholderObject; } } }