Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
micmerchant opened this issue Mar 8, 2019 · 2 comments

Comments

@micmerchant
Copy link
Contributor

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

@fredericDelaporte
Copy link
Member

Regression of 5.0.

@fredericDelaporte
Copy link
Member

Back-ported to 5.1.5 and 5.0.7.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants