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;
        }
    }

}
posted @ 2012-01-04 23:39 sdhjl2000 阅读(...) 评论(...) 编辑 收藏