Romain Meresse
Romain Meresse

Reputation: 3044

NHibernate serializing lazy-loaded entities with WCF

I'm trying to send NH entities through the wire using WCF. I've got a complex graph of lazy-loaded objects.. I tried to implement a custom DataContractSurrogate to force initialization when serializing. Here is the code :

public class HibernateDataContractSurrogate : IDataContractSurrogate
{
    public HibernateDataContractSurrogate()
    {
    }

    public Type GetDataContractType(Type type)
    {
        // Serialize proxies as the base type
        if (typeof(INHibernateProxy).IsAssignableFrom(type))
        {
            type = type.GetType().BaseType;
        }

        // Serialize persistent collections as the collection interface type
        if (typeof(IPersistentCollection).IsAssignableFrom(type))
        {
            foreach (Type collInterface in type.GetInterfaces())
            {
                if (collInterface.IsGenericType)
                {
                    type = collInterface;
                    break;
                }
                else if (!collInterface.Equals(typeof(IPersistentCollection)))
                {
                    type = collInterface;
                }
            }
        }

        return type;
    }

    public object GetObjectToSerialize(object obj, Type targetType)
    {
        if (obj is INHibernateProxy)
        {
            obj = ((INHibernateProxy)obj).HibernateLazyInitializer.GetImplementation();
        }

        // Serialize persistent collections as the collection interface type
        if (obj is IPersistentCollection)
        {
            IPersistentCollection persistentCollection = (IPersistentCollection)obj;
            persistentCollection.ForceInitialization();
            obj = persistentCollection.Entries(null); // This returns the "wrapped" collection
        }

        return obj;
    }

    public object GetDeserializedObject(object obj, Type targetType)
    {
        return obj;
    }

    public object GetCustomDataToExport(MemberInfo memberInfo, Type dataContractType)
    {
        return null;
    }

    public object GetCustomDataToExport(Type clrType, Type dataContractType)
    {
        return null;
    }

    public void GetKnownCustomDataTypes(Collection<Type> customDataTypes)
    {
    }

    public Type GetReferencedTypeOnImport(string typeName, string typeNamespace, object customData)
    {
        return null;
    }

    public CodeTypeDeclaration ProcessImportedType(CodeTypeDeclaration typeDeclaration, CodeCompileUnit compileUnit)
    {
        return typeDeclaration;
    }
}

However, I keep getting exceptions :

NHibernate.Exceptions.GenericADOException: could not initialize a collection [SQL trace] ---> System.ObjectDisposedException: Session is closed!

Looking at the stacktrace, it appears that this line persistentCollection.ForceInitialization(); is throwing the exception.

What can I do?

PS: I'd like to use DTO instead of serializing complex NH entities, however it's not possible here.

Upvotes: 2

Views: 3363

Answers (2)

Andrew Skirrow
Andrew Skirrow

Reputation: 3451

You can't lazy-load a collection after you've closed the NHibernate.ISession object from which it was loaded. The only options you have are:

  1. Keep the ISession open until you've serialized the data.
  2. Turn off lazy loading.
  3. make sure you fetch all the lazy loaded collections before closing the session.

Upvotes: 1

Related Questions