(answering question about the code)
nmeena wrote:
Initially there is only one for loop to set the ordinals, but in the modified code there are two for loops, starting at 79 and another one from line 113,
the first for loop is setting the ordinals of the already created columns in the datatable matching with the columns output by the query, second loop is setting the ordinal of remaining output columns.
this solves the problem and covers all the scenarios. Can you please explain a bit the scenarios which can still not be covered here from the modified code?
Projections use a 2 step process. Step 1 is filling an object array where each position is filled by the value projector at that index by passing in the values array obtained from the datareader. Step 2 is consuming the array created in step 1 to an element in the destination, be it a datatable row, entity or other.
I now see you have two loops, not one. I overlooked that. Say I have a datatable with the columns: A, B, C, D.
I have a query which returns: C, B, D, E. 'fieldsPersistenceInfo' is the array with the persistence infos for this query, and it contains the persistence infos for C, B, D, E in that order.
to produce a projection row for A, B, C, D, I have to add the projectors for A, B, C and D, in that order, to the valueProjectors list. Your first loop skips 'A', as it's not in the schemaRowPerColumnName list (meaning it's not in the query's resultset). So it doesn't handle all cases. It only handles the cases where you have appended columns to the datatable. Our code doesn't do this either, I'm not blaming you for anything, just to show you it's not a 'fix for all'.
It should do this:
- per column in the datatable, it should create a valueprojector which either reads the value from index X if the column is in the resultset at index X, or insert NULL if not (so a dummy projector)
- skip the rest.
- send this valueProjector list to the projector.
IMHO you can achieve this with the projector api: setup the projectors as you want to, which match the datatable you want to read into, and then use the DataProjectorToDataTable class to project the resultset to the existing datatable. The DataProjectorToDataTable class already can deal with existing columns and doesn't re-create them. You can also pick that class' sourcecode and alter it a bit (it now always tries to recreate columns, and adds a column for each projector in the list).
As this type of code is very cumbersome to get right, and the getmultiasdatatable is primarily meant for fetching into an empty datatable, we won't change the runtime at this point. I'd like to suggest to you to use the projector api instead for this particular query/datatable. If you need help with that, please let me know.