-
Notifications
You must be signed in to change notification settings - Fork 936
Description
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
- Fix TransientObjectException in ISession.IsDirty() with many-to-one (Fix #1419 - ISession.IsDirty() shouldn't throw exception for transient many-to-one object in a session #1420)
Add an explicit check for transient objects in ManyToOne.IsDirty
Fixes ISession.IsDirty() shouldn't throw exception for transient many-to-one object in a session #1419
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