Closed
Description
Invalid parameter conversion for enums parameters in Linq queries with GROUP BY and CASE statement in NHibernate 5.3.
In some scenarios are enum parameters convert as int instead of nvarchar.
Most probably related to 2439 and 2649
One of our scenario failed after upgrade from 5.2.6 to 5.3.5. It is still failing after upgrade to 5.3.6.
Here is simplified example:
public enum InvoiceType
{
INCOME,
OUTCOME
}
public class Invoice
{
public virtual InvoiceType InvoiceType {get;set;}
public virtual DateTime Date {get;set;}
}
public class InvoiceItem
{
public virtual long ItemTypeid {get;set;}
public virtual decimal Price {get;set;}
public virtual Invoice Invoice {get;set;}
}
Failing query:
Session.Query<InvoiceItem>()
.Where(it=> it.Invoice.Date >= new DateTime(2021,1,1))
.GroupBy(it =>
new
{
ItemTypeId = it.ItemTypeId,
InvoceType = it.Invoice.InvoiceType
})
.Select(gr => new
{
TypeId = gr.Key.ItemTypeId ,
Income = gr.Key.InvoiceType == InvoiceType.INCOME ? gr.Sum(y => y.Price) : 0,
Outcome= gr.Key.InvoiceType == InvoiceType.OUTCOME ? gr.Sum(y => y.Price) : 0,
})
.ToList();
Error:
NHibernate.Util.ADOExceptionReporter Conversion failed when converting the nvarchar value 'INCOME ' to data type int.
System.Data.SqlClient.SqlException (0x80131904): Conversion failed when converting the nvarchar value 'INCOME ' to data type int.
v System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction)
v System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose)
v System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady)
v System.Data.SqlClient.SqlDataReader.TryHasMoreRows(Boolean& moreRows)
v System.Data.SqlClient.SqlDataReader.TryReadInternal(Boolean setTimeout, Boolean& more)
v System.Data.SqlClient.SqlDataReader.Read()
v NHibernate.Driver.NHybridDataReader.Read()
v NHibernate.Loader.Loader.DoQuery(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies, IResultTransformer forcedResultTransformer, QueryCacheResultBuilder queryCacheResultBuilder)
v NHibernate.Loader.Loader.DoQueryAndInitializeNonLazyCollections(ISessionImplementor session, QueryParameters queryParameters, Boolean returnProxies, IResultTransformer forcedResultTransformer, QueryCacheResultBuilder queryCacheResultBuilder)
v NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters, IResultTransformer forcedResultTransformer, QueryCacheResultBuilder queryCacheResultBuilder)
NHibernate.Util.ADOExceptionReporter Conversion failed when converting the nvarchar value 'INCOME ' to data type int.
System.Data.SqlClient.SqlException (0x80131904): Conversion failed when converting the nvarchar value 'INCOME ' to data type int.
v NHibernate.Loader.Loader.DoList(ISessionImplementor session, QueryParameters queryParameters, IResultTransformer forcedResultTransformer, QueryCacheResultBuilder queryCacheResultBuilder)
v NHibernate.Loader.Loader.ListIgnoreQueryCache(ISessionImplementor session, QueryParameters queryParameters)
v NHibernate.Loader.Hql.QueryLoader.List(ISessionImplementor session, QueryParameters queryParameters)
v NHibernate.Hql.Ast.ANTLR.QueryTranslatorImpl.List(ISessionImplementor session, QueryParameters queryParameters)
v NHibernate.Engine.Query.HQLQueryPlan.PerformList(QueryParameters queryParameters, ISessionImplementor session, IList results)
v NHibernate.Impl.SessionImpl.List(IQueryExpression queryExpression, QueryParameters queryParameters, IList results, Object filterConnection)
However it works after I move condition inside Sum:
Session.Query<InvoiceItem>()
.Where(it=> it.Invoce.Date >= new DateTime(2021,1,1))
.GroupBy(it => new {ItemTypeId = it.ItemTypeId})
.Select(gr =>
new
{
TypeId = gr.Key.ItemTypeId ,
Income = gr.Sum(y => y.Invoce.InvoiceType == InvoiceType.INCOME ? y.Price : 0),
Outcome= gr.Sum(y => y.Invoce.InvoiceType == InvoiceType.OUTCOME ? y.Price : 0),
})
.ToList();