Skip to content

System.Reflection.TargetException when an interface is used as class mapping proxy definition #2043

@micmerchant

Description

@micmerchant

Hello,

as u may know, we are currently updating from an old NHibernate 4 (4.0.3) version to the current NHibernate 5 (5.2.3) version and are facing some issues.

We often declare an interface as class proxy, as it is stated in the Mapping Documetation.

proxy (optional): Specifies an interface to use for lazy initializing proxies. You may specify the name of the class itself.

With NHibernate 5 a System.Reflection.TargetException is thrown now, when a Many-To-One reference is updated with a proxy object. I first thought, that this only happens in case of union-subclass-mappings (cause we often used proxy definitions in inheritance mappings), but this isn't the case. It is independ from inheritance mappings. Let me explain.

This is an example model:

public class EntityWithInterfaceProxyDefinition: IEntityProxy
{
	public virtual Guid Id { get; set; }
	public virtual string Name { get; set; }
}

This is the model where it is referenced:

public class EntityWithInterfaceLookup
{
	public virtual Guid Id { get; set; }
	public virtual string Name { get; set; }
	public virtual IEntityProxy EntityLookup { get; set; }
}

I've deactivated the reflection optimization to better debug this problem:

Cfg.Environment.UseReflectionOptimizer = false;

The exception was triggerd from the flush after the update and is thrown here:

protected virtual object GetIdentifierPropertyValue(object entity)
{
	return idGetter.Get(entity);
}

This makes of course sense, because:

entity.GetType().ToString()
"IEntityProxyProxy"
entity.GetType().BaseType.ToString()
"System.Object"
entity.GetType().GetInterfaces()
{System.Type[3]}
    [0]: {Name = "ISerializable" FullName = "System.Runtime.Serialization.ISerializable"}
    [1]: {Name = "INHibernateProxy" FullName = "NHibernate.Proxy.INHibernateProxy"}
    [2]: {Name = "IEntityProxy" FullName = "NHibernate.Test.NHSpecificTest.IlogsProxyTest.IEntityProxy"}
idGetter
{NHibernate.Properties.BasicPropertyAccessor.BasicGetter}
    Method: {System.Guid get_Id()}
    Property: {System.Guid Id}
    PropertyName: "Id"
    ReturnType: {Name = "Guid" FullName = "System.Guid"}
    clazz: {Name = "EntityWithInterfaceProxyDefinition" FullName = "NHibernate.Test.NHSpecificTest.IlogsProxyTest.EntityWithInterfaceProxyDefinition"}
    @property: {System.Guid Id}
    propertyName: "Id"

As you can see, the given entity parameter doesn't inherit from the "EntityWithInterfaceProxyDefinition" class, which is the parent class of the idGetter. So you get an TargetException by invoking the idGetter.

I guess this fix raised this issue:

SHA-1: da56a73

I've attached some test mapping classes, as well as a test fixture with two tests to reproduce this problem. The test "UpdateEntityWithInterfaceLookup" fails the other one doesn't fail (cause it uses the clsas itself as proxy)

I know removing the proxy definition should be the workaround for this issue. But as long you don't say, we are doing something completly wrong, i would rather avoid that.

Thx, in adavance.
TargetExceptionTest.zip

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions