ArgumentException in Oracle - Value isn't of type 'System.Int16

Posts   
 
    
TomDog
User
Posts: 618
Joined: 25-Oct-2005
# Posted on: 26-Feb-2019 11:10:22   
Finding.Where(f => f.FindingSourceID != 5)

works fine in SQL but in Oracle gives

Value isn't of type 'System.Int16'Parameter name: value

 at SD.LLBLGen.Pro.ORMSupportClasses.SystemTypeConverterBase`1.ConvertTo(ITypeDescriptorContext context, CultureInfo culture, Object value, Type destinationType)
   at SD.LLBLGen.Pro.ORMSupportClasses.DbSpecificCreatorBase.CreateParameter(IEntityFieldCore field, IFieldPersistenceInfo persistenceInfo, ParameterDirection direction, Object valueToSet)
   at SD.LLBLGen.Pro.ORMSupportClasses.FieldCompareValuePredicate.ToQueryText(Boolean inHavingClause)
   at SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.ToQueryText(Boolean inHavingClause)
   at SD.LLBLGen.Pro.ORMSupportClasses.PredicateExpression.ToQueryText(Boolean inHavingClause)
   at SD.LLBLGen.Pro.ORMSupportClasses.DynamicQueryEngineBase.AppendWhereClause(IPredicate filter, QueryFragments destination, IQuery query)
   at SD.LLBLGen.Pro.DQE.Oracle.DynamicQueryEngine.CreateSelectDQImpl(QueryParameters parameters, DbConnection connectionToUse)
   at SD.LLBLGen.Pro.DQE.Oracle.DynamicQueryEngine.CreatePagingSelectDQ(QueryParameters parameters, DbConnection connectionToUse)
   at SD.LLBLGen.Pro.ORMSupportClasses.DynamicQueryEngineBase.CreateSelectDQ(QueryParameters parameters, DbConnection connectionToUse)
   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterCore.CreateSelectDQ(QueryParameters parameters)
   at AQD.Model.Oracle.DataAccessAdapter.CreateSelectDQ(QueryParameters parameters)
   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterCore.FetchEntityCollectionInternal(QueryParameters parameters)
   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterCore.FetchEntityCollection(QueryParameters parameters)
   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.<>c__DisplayClass10_0.<FetchEntityCollection>b__0()
   at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProvider2.ExecuteEntityProjection(QueryExpression toExecute)
   at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.ExecuteExpression(Expression handledExpression, Type typeForPostProcessing)
   at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProProviderBase.System.Linq.IQueryProvider.Execute(Expression expression)
   at SD.LLBLGen.Pro.LinqSupportClasses.LLBLGenProQuery`1.System.Collections.IEnumerable.GetEnumerator()

Workaround:

Finding.Where(f => f.FindingSourceID != (short)5)

FindingSourceID is a short?

Oracle

this.AddElementFieldMapping("FindingEntity", "FindingSourceID", "FINDING_SOURCE_ID", true, "Decimal", 0, 5, 0, false, "", new SD.LLBLGen.Pro.ORMSupportClasses.ChangeTypeConverter<System.Int16>(), typeof(System.Int32), 32);

SQL

this.AddElementFieldMapping("FindingEntity", "FindingSourceID", "Finding_Source_ID", true, "SmallInt", 0, 5, 0, false, "", null, typeof(System.Int16), 32);

version="5.5.2-hotfix-20190225"

Jeremy Thomas
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 26-Feb-2019 16:02:21   

FindingSourceID is a short?

Heh I first thought "Why are you asking me?" but you meant Nullable<short> smile

the problem here is that the value is FROM model TO DB, so it uses the TO convert. This means it converts a value in the type of the model TO the type of the DB. The value therefore has to be a short, otherwise the type converter doesn't work. On SQL Server you're not using the type converter so it works there.

The type converter normally works fine as you convert a short inside the entity to an int32 parameter and when the is read from the DB it is converted to a short.

It looks odd, as normally there's an implicit conversion going on most of the time between ints and shorts but here the type converter does a strict 'is' check of the value with the model type (short) and that fails. So this is 'by design' (I know it's crappy, but it is simple_smile . It's not really 'intentional' but a side effect of the untypedness of the predicate system)

Frans Bouma | Lead developer LLBLGen Pro
TomDog
User
Posts: 618
Joined: 25-Oct-2005
# Posted on: 27-Feb-2019 09:27:14   

But if I put the typeconverter back that I needed pre v5.5 it works.

this.AddElementFieldMapping("FindingEntity", "FindingSourceID", "FINDING_SOURCE_ID", true, "Decimal", 0, 5, 0, false, "", new AQD.Helpers.TypeConverters.SmallIntegerNumericConverter(), typeof(System.Int32), 32);
Jeremy Thomas
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 27-Feb-2019 10:01:03   

But that's your own type converter I presume? If so, it doesn't do a test whether the value to use to convert to the destination type is actually of the source type, most likely (as that would fail). The system type converters shipped in the runtime do, hence the problem here.

It might be this check is a bit too strict, after all, one could argue the conversion will fail anyway later on if the value can't be converted to the destination type anyway.

We'll look into whether we can lift this restriction.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 27-Feb-2019 10:58:22   

The system type converter uses a cast to pass the value on to the actual conversion method. The test with 'is' is to prevent a lame invalidcastexception without more info. However, it's a bit too strict: value conversions aren't taken into account (casting an int to a short is valid after all).

So we'll change the code a bit: we'll do the cast first and if it results in an exception, we'll throw the exception we're doing now. This should both prevent values that are totally invalid (passing a string to this type converter for instance) and give more flexibility.

(edit) Of course this fails because the value is boxed... disappointed Will see if there's a workaround around that.

//this works: int i = 42; short j = (int)i;

// this fails: object i = 42; short j = (int)i;

(edit) can only solve this by checking first if it's a short, if not, use Convert.ChangeType() on the value, which has the side effect that passing in "1" also works: it's happily converted to the destination type. I guess it's a bonus for the one edge case where this pops up (the input of "1" should have been caught earlier by the user code anyway)

Fixed in next build.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39588
Joined: 17-Aug-2003
# Posted on: 27-Feb-2019 16:55:08   

Hotfix is now available

Frans Bouma | Lead developer LLBLGen Pro
TomDog
User
Posts: 618
Joined: 25-Oct-2005
# Posted on: 28-Feb-2019 11:40:30   

Yep sorted - thankssmile

Jeremy Thomas