Skip to content

NH-3290 - AliasToBeanResultTransformer throws error when setting uint field/property using an int value #1139

Open
@nhibernate-bot

Description

@nhibernate-bot

Christopher McGinnis created an issue — 14th October 2012, 3:23:22:

I was storing a uint flags enum in a sql server db column using the int data type. i only need to pull out the flags column as well as one additional column so i used a projection list and AliasToBean as the result transformer where MyEntity represents the table row. AliasToBeanResultsTransformer throws an exception when setting a field/property of type uint, enum or otherwise, using an int value.


Christopher McGinnis added a comment — 14th October 2012, 4:22:58:

Pull request: #153


Christopher McGinnis added a comment — 14th October 2012, 6:56:51:

Updated the test case using the project in github for the skeleton


Oskar Berggren added a comment — 14th October 2012, 22:55:00:

Why do you need to mix types like this? Can't you use the enum in the mapping also?


Christopher McGinnis added a comment — 15th October 2012, 0:26:37:

I have a table which stores a user's originally uploaded file, my parsed representation of that file which has been serialized, and the serialization method flags. An int flags enum doesn't allow for the flag value of 0x80000000 so a uint is needed instead.

The regular entity mapping works as expected, but in my particular scenario I generally only need to retrieve the serialized data and storage flags but not the user's original file. This leads me to use a projection list so only the data that is needed for deserialization process is retrieved. However when I use AliasToBeanResultsTransformer I get the binary data but the storage flags field has a value of 0 which then causes a deserialization error.

This problem isn't major by any means and is easily worked around but since uint data is stored in sql server as an int I expect to get it back out as a uint regardless of whether it is through an entity mapping or a results transformer.


Oskar Berggren added a comment — 15th October 2012, 7:57:20:

In your test the entity contains an int. But above, are you saying that in your production code, the mapped property in the entity is typed as the uint enum?

To put it another way: Given these two cases:

  1. DB int mapped to uint enum in entity.
  2. DB int mapped to uint enum by AliasToBean.

Are you saying that case 1 currently works?

Given that MS SQL Server has no unsigned integer type, I suppose this could be a useful addition.


Christopher McGinnis added a comment — 15th October 2012, 18:02:35:

Yes. The reason I typed the entity with an it is because that is what gets stored into SQL Server.

#1 works as expected
#2 fails to set a uint field/property using an int value

I will update the test to to represent use cases 1 and 2.


Christopher McGinnis added a comment — 15th October 2012, 21:14:32:

Actually, in trying to write a test case for #1 I am finding that it isn't working the same as in my main project source. I am beginning to wonder if the difference might be due to the fact that I am using Fluent in my main project.

The test cases for #2 are failing/working as expected.

I am going to keep working on the test case for #1 but would appreciate any pointers you might have.


Christopher McGinnis added a comment — 15th October 2012, 21:28:32:

This test case for #1 work:

public enum EnumFlags : uint { None = 0x00000000, Flag1 = 0x00000001, Flag2 = 0x00000002, Flag3 = 0x00000004, Flag4 = 0x00000008,

ComboOdd = Flag1 | Flag3,
ComboEven = Flag2 | Flag4,
}

public class FluentDomainClass
{
public virtual int Id { get; set; }

public virtual EnumFlags StoredFlags { get; set; }

public class EntityMapping : ClassMap
{
public EntityMapping()
{
Table("NH3290");
Id(x => x.Id).GeneratedBy.Assigned();
Map(x => x.StoredFlags).CustomType();
}
}
}

public void FluentTest() { using (var factory = Fluently.Configure() .Database ( MsSqlConfiguration.MsSql2008 .ConnectionString(@"Data Source=localhost\SQLEXPRESS;Initial Catalog=NHTEST;Integrated Security=True;Pooling=False") .ShowSql() ) .Mappings(m => m.FluentMappings.AddFromAssembly(Assembly.GetExecutingAssembly())) .BuildSessionFactory()) { using (ISession session = factory.OpenSession()) { var entity = new FluentDomainClass(); entity.Id = 2; entity.StoredFlags = EnumFlags.ComboEven; session.Save(entity); session.Flush();
  	var result = session.CreateCriteria<FluentDomainClass>()
  	.Add(Restrictions.Eq("Id", 2))
  	.UniqueResult<FluentDomainClass>()
  	;

  	Assert.AreEqual(EnumFlags.ComboEven, result.StoredFlags);
  }

}
}


Christopher McGinnis added a comment — 15th October 2012, 21:34:03:

This test for #1 does not work:

public class DomainClass
{
public virtual int Id { get; set; }

public virtual EnumFlags StoredFlags { get; set; }
}

public void EntityEnumPropertyShouldBeSet() { using (ISession session = this.OpenSession()) { var result = session.CreateCriteria() .Add(Restrictions.Eq("Id", 1)) .UniqueResult() ;
  Assert.AreEqual(EnumFlags.ComboEven, result.StoredFlags);

}
}

------ Test started: Assembly: NHibernate.Test.dll ------

Test 'NHibernate.Test.NHSpecificTest.NH3290.SampleTest.EntityEnumPropertyShouldBeSet' failed: NHibernate.PropertyAccessException : Invalid Cast (check your mapping for property type mismatches); setter of NHibernate.Test.NHSpecificTest.NH3290.DomainClass
----> System.InvalidCastException : Specified cast is not valid.
TearDown : NHibernate.PropertyAccessException : Invalid Cast (check your mapping for property type mismatches); setter of NHibernate.Test.NHSpecificTest.NH3290.DomainClass
----> System.InvalidCastException : Specified cast is not valid.
at NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValuesWithOptimizer(Object entity, Object[] values)
at NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValues(Object entity, Object[] values)
at NHibernate.Persister.Entity.AbstractEntityPersister.SetPropertyValues(Object obj, Object[] values, EntityMode entityMode)
at NHibernate.Engine.TwoPhaseLoad.InitializeEntity(Object entity, Boolean readOnly, ISessionImplementor session, PreLoadEvent preLoadEvent, PostLoadEvent postLoadEvent)
at NHibernate.Loader.Loader.InitializeEntitiesAndCollections(IList hydratedObjects, Object resultSetId, ISessionImplementor session, Boolean readOnly)
at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies)
at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters)
at NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters)
at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet1 querySpaces, IType[] resultTypes) at NHibernate.Loader.Criteria.CriteriaLoader.List(ISessionImplementor session) at NHibernate.Impl.SessionImpl.List(CriteriaImpl criteria, IList results) at NHibernate.Impl.CriteriaImpl.List(IList results) at NHibernate.Impl.CriteriaImpl.List() at NHibernate.Impl.CriteriaImpl.UniqueResult() at NHibernate.Impl.CriteriaImpl.UniqueResult<T>() NHSpecificTest\NH3290\SampleTest.cs(89,0): at NHibernate.Test.NHSpecificTest.NH3290.SampleTest.EntityEnumPropertyShouldBeSet() --InvalidCastException at (Object , Object[] , SetterCallback ) at NHibernate.Bytecode.Lightweight.AccessOptimizer.SetPropertyValues(Object target, Object[] values) at NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValuesWithOptimizer(Object entity, Object[] values) --TearDown at NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValuesWithOptimizer(Object entity, Object[] values) at NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValues(Object entity, Object[] values) at NHibernate.Persister.Entity.AbstractEntityPersister.SetPropertyValues(Object obj, Object[] values, EntityMode entityMode) at NHibernate.Engine.TwoPhaseLoad.InitializeEntity(Object entity, Boolean readOnly, ISessionImplementor session, PreLoadEvent preLoadEvent, PostLoadEvent postLoadEvent) at NHibernate.Loader.Loader.InitializeEntitiesAndCollections(IList hydratedObjects, Object resultSetId, ISessionImplementor session, Boolean readOnly) at NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) at NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies) at NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters) at NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters) at NHibernate.Loader.Loader.List(ISessionImplementor session, QueryParameters queryParameters, ISet1 querySpaces, IType[] resultTypes)
at NHibernate.Hql.Ast.ANTLR.Loader.QueryLoader.List(ISessionImplementor session, QueryParameters queryParameters)
at NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.List(ISessionImplementor session, QueryParameters queryParameters)
at NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results)
at NHibernate.Impl.SessionImpl.List(String query, QueryParameters queryParameters, IList results)
at NHibernate.Impl.SessionImpl.List(String query, QueryParameters parameters)
at NHibernate.Impl.SessionImpl.Find(String query, Object<] values, IType[> types)
at NHibernate.Impl.SessionImpl.Delete(String query, Object<] values, IType[> types)
at NHibernate.Impl.SessionImpl.Delete(String query)
NHSpecificTest\NH3290\SampleTest.cs(41,0): at NHibernate.Test.NHSpecificTest.NH3290.SampleTest.OnTearDown()
TestCase.cs(162,0): at NHibernate.Test.TestCase.TearDown()
--InvalidCastException
at (Object , Object[] , SetterCallback )
at NHibernate.Bytecode.Lightweight.AccessOptimizer.SetPropertyValues(Object target, Object[] values)
at NHibernate.Tuple.Entity.PocoEntityTuplizer.SetPropertyValuesWithOptimizer(Object entity, Object[] values)


Oskar Berggren added a comment — 21st October 2012, 10:29:29:

If you grab the generated XML config from fluent, what is the difference compared to your manual HBM?

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions