TypedView mapped to Stored Proc cannot handle underscores in fields names

Posts   
 
    
derrick
User
Posts: 40
Joined: 14-Jan-2004
# Posted on: 16-Jun-2020 22:04:35   

I just upgraded from 5.6.2 to 5.7.0 and the field mappings between a Stored Proc Resultset and a TypedView do not work for fields with underscores in their names.

The naming convention of fields in the database are like event_name, attendee_count, etc and those are mapped to fields in the TypedView as EventName, AttendeeCount etc.

The problem is that with the upgrade to 5.7 any column name with an underscore does not get mapped properly. The resulting TypedView has the correct number of rows and columns but empty values for any field with an underscore in the field name coming from the proc. NOTE: fields with no underscores in their names are mapped fine and their values are returned as expected in the TypedView.

so for a proc that does this:

SELECT event_name, attendee_count, age FROM ...

the resulting TypedView has 3 fields named EventName, AttendeeCount, Age and only Age contains values.

Details: LLBLGenPro 5.7 (5.7.0) RTM 25-May-2020 Runtime Version 5.7.0.0 Adapter Templates .Net Framework 4.7.2 Microsoft SQL Server 2014 (SP2-GDR) (KB4505217) - 12.0.5223.6 (X64) May 26 2019 20:36:50 Copyright (c) Microsoft Corporation Standard Edition (64-bit) on Windows NT 6.3 <X64> (Build 14393: )

derrick
User
Posts: 40
Joined: 14-Jan-2004
# Posted on: 16-Jun-2020 22:18:42   

UPDATE:

I downloaded the runtime source and the issue is in SD.LLBLGen.Pro.ORMSupportClasses.DataTableFiller.Fill(...).

the number of items in List<IDataValueProjector> valueProjectors that is passed to ProjectionUtils.FetchProjectionFromReader() is different between v5.7 and v.5.6.2

in v5.6.2 that List has an item for every field returned. In v5.7 it only has items for fields with no underscores because the while loop hits a continue and those are never added to valueProjecters List.

Seems like a bug to me?

ProjectionUtils.FetchProjectionFromReader(valueProjectors, projector, dataSource, queryExecuted.ManualRowsToSkip, queryExecuted.ManualRowsToTake, queryExecuted.RequiresClientSideLimitation, queryExecuted.RequiresClientSideDistinctFiltering, queryExecuted.RequiresClientSidePaging, true, false, new Dictionary<int, TypeConverter>(), queryExecuted);

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 17-Jun-2020 08:54:25   

Thanks for the info, we'll look into it!

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 17-Jun-2020 10:03:05   

Reproduced. Will also check queryspec mapped poco types on the same resultset.

(edit) A queryspec poco mapped on the same resultset fetches fine, so it's going wrong only for DataTable based typed views mapped onto a resultset from a proc which contains underscores. We haven't done any work in that particular pipeline in v5.7 so it'll be interesting to see what this bug is caused by.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 17-Jun-2020 11:34:08   

It's also part of 5.6.3, a bugfix was made in April which seems to cause this.

Fix for LLBLMAIN-2258: When a stored procedure resultset, with a datatable based typedview mapped onto it, receives new fields and the project isn't synced/regenerated again, it could be the projection of the new resultset to the typedview fails

(https://www.llblgen.com/tinyforum/Messages.aspx?ThreadID=27033)

It's a side effect of the fix, and therefore we'll address this in both 5.6.3 and 5.7.0.

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 17-Jun-2020 12:58:05   

Fixed in hotfix builds 5.6.4 and 5.7.1, which are now available (the nuget packages will be up shortly, after Nuget has vetted the packages with their ultraslow code)

Frans Bouma | Lead developer LLBLGen Pro
derrick
User
Posts: 40
Joined: 14-Jan-2004
# Posted on: 18-Jun-2020 17:07:09   

Frans,

I'm looking at 5.7.1 hotfix and I am getting this exception (JSON formatted below). It looks like an index (sourceColumnIndex) is being incremented before it is used to access the DataRowCollection so its value is always +1 of what it should be?

top of while loop, so dsIndex is always sourceColumnIndex + 1

int sourceColumnIndex = dsIndex;
dsIndex++;

if this condition is met, sourceColumnIndex is assigned dsIndex (which increments it by 1)

// check if the column is mapped through a mapping and the name is different/renamed in the typedview
// this is ok as the only situation where this can work is when columns are added to the resultset that aren't mapped. 
// so fpiIndex is an ok index to read the sourcecolumn for.  
if(fieldsPersistenceInfo[fpiIndex]?.SourceColumnName == resultsetColumnName)
{
    // same, so use the column name at the fpiIndex in the datatable passed in. 
    sourceColumnIndex = dsIndex;
}

sourceColumnIndex is +1 of what it should be which eventually throws IndexOutOfRangeException

Type typeOfColumn = (Type)schemaTable.Rows[sourceColumnIndex]["DataType"];

Exception:

{
   "Message":"An error has occurred.",
   "ExceptionMessage":"There is no row at position 19.",
   "ExceptionType":"System.IndexOutOfRangeException",
   "StackTrace":"   at System.Data.RBTree`1.GetNodeByIndex(Int32 userIndex)\r\n   at System.Data.DataRowCollection.get_Item(Int32 index)\r\n   at SD.LLBLGen.Pro.ORMSupportClasses.DataTableFiller.Fill(IDataReader dataSource, DataTable toFill, IFieldPersistenceInfo[] fieldsPersistenceInfo, IRetrievalQuery queryExecuted) in C:\\junk\\llblgen_v5.7.1\\Frameworks\\LLBLGen Pro\\RuntimeLibraries\\ORMSupportClasses\\Miscellaneous\\DataTableFiller.cs:line 141\r\n   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterCore.ExecuteMultiRowDataTableRetrievalQuery(IRetrievalQuery queryToExecute, DbDataAdapter dataAdapterToUse, DataTable tableToFill, IFieldPersistenceInfo[] fieldsPersistenceInfo) in C:\\junk\\llblgen_v5.7.1\\Frameworks\\LLBLGen Pro\\RuntimeLibraries\\ORMSupportClasses\\AdapterSpecific\\DataAccessAdapterCore.cs:line 858\r\n   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterCore.FetchTypedView(ITypedView2 typedViewToFill, IRetrievalQuery queryToUse) in C:\\junk\\llblgen_v5.7.1\\Frameworks\\LLBLGen Pro\\RuntimeLibraries\\ORMSupportClasses\\AdapterSpecific\\DataAccessAdapterCore.cs:line 2972\r\n   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.<>n__15(ITypedView2 typedViewToFill, IRetrievalQuery queryToUse)\r\n   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.<>c__DisplayClass16_0.<FetchTypedView>b__0() in C:\\junk\\llblgen_v5.7.1\\Frameworks\\LLBLGen Pro\\RuntimeLibraries\\ORMSupportClasses\\AdapterSpecific\\DataAccessAdapterBase.cs:line 350\r\n   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.ExecuteWithActiveRecoveryStrategy(Action toExecute) in C:\\junk\\llblgen_v5.7.1\\Frameworks\\LLBLGen Pro\\RuntimeLibraries\\ORMSupportClasses\\AdapterSpecific\\DataAccessAdapterBase.cs:line 892\r\n   at SD.LLBLGen.Pro.ORMSupportClasses.DataAccessAdapterBase.FetchTypedView(ITypedView2 typedViewToFill, IRetrievalQuery queryToUse) in C:\\junk\\llblgen_v5.7.1\\Frameworks\\LLBLGen Pro\\RuntimeLibraries\\ORMSupportClasses\\AdapterSpecific\\DataAccessAdapterBase.cs:line 350\r\n   at hikurangi.Api.UnapprovedLeadsController.GetAllUnapprovedLeads() in C:\\E\\hikurangi\\Api\\UnapprovedLeadsController.cs:line 37\r\n   at lambda_method(Closure , Object , Object[] )\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_2.<GetExecutor>b__2(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__3.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n   at hikurangi.Api.AddChallengeOnUnauthorizedResult.<ExecuteAsync>d__9.MoveNext() in C:\\E\\hikurangi\\Api\\IdentityBasicAuthenticationAttribute.cs:line 143\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.AuthenticationFilterResult.<ExecuteAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()"
}

Thank you for your help with this

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 18-Jun-2020 18:05:58   

Ah I see it! I use the dsIndex value, but it's indeed incremented on line 90. How embarrassing. Our test succeeds because there are more fields following that particular underscore containing test field. However if it's at the end of the select list, it fails. Will correct this now and push a new hotfix

Frans Bouma | Lead developer LLBLGen Pro
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39614
Joined: 17-Aug-2003
# Posted on: 18-Jun-2020 18:29:18   

We pushed new hotfix builds for 5.6.4 and 5.7.1 and this should fix the issue, please get the latest hotfix build from nuget (when it's passed the vetting step)

Frans Bouma | Lead developer LLBLGen Pro
derrick
User
Posts: 40
Joined: 14-Jan-2004
# Posted on: 19-Jun-2020 20:40:54   

that fixed the issue. thanks.