Strange error on stringed Linq calls - iterator

I inherited this code that takes an IEnumerable and performs a series of Selects on it and then attempts to call Sum on the remaining records after the Selects are performed. The code reads as:
var totalrecs = records.Select(row => new RowInfo(RowID = row.RowID, SomeData = row.SomeData})
.Select(ri => new {RowInfo = ri, XMLData = GetXMLFileForRecord(ri)})
.Select(data => ParseAndUpdateRecords(data.RowInfo, data.XmlData))
.Sum();
where 'records' is an IEnumerable.
The error is for attempting to convert a decimal to a long and from the StackTrace seems to be occurring when calling Sum on the Iterator that results from the three Select calls.
The stack trace is:
Exception:Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot implicitly convert type 'decimal' to 'long'. An explicit conversion exists (are you missing a cast?)
at CallSite.Target(Closure , CallSite , Object )
at RecordCapture.Controller.<CaptureAndUpdateRecords>b__10(Object row)
at System.Linq.Enumerable.<>c__DisplayClass12`3.<CombineSelectors>b__11(TSource x)
at System.Linq.Enumerable.<>c__DisplayClass12`3.<CombineSelectors>b__11(TSource x)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.Sum(IEnumerable`1 source)
at RecordCapture.Controller.CaptureAndUpdateRecords()
at RecordCapture.Controller.<Start>b__1()
StackTrace: at CallSite.Target(Closure , CallSite , Object )
at RosterCapture.Controller.<CaptureAndUpdateRosters>b__10(Object row)
at System.Linq.Enumerable.<>c__DisplayClass12`3.<CombineSelectors>b__11(TSource x)
at System.Linq.Enumerable.<>c__DisplayClass12`3.<CombineSelectors>b__11(TSource x)
at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
at System.Linq.Enumerable.Sum(IEnumerable`1 source)
at RecordCapture.Controller.CaptureAndUpdateRecords()
at RecordCapture.Controller.<Start>b__1()
The Selects return an Iterator and there does not seem to be any way to get an accurate count of what the result of the Selects is.
Interestingly, if records is empty, calling Sum simply returns a zero and does not throw an error.

Do you want to Sum integers or decimals? Use the Generic type appropriate, and cast the result if necessary. See http://msdn.microsoft.com/en-us/library/system.linq.enumerable.sum.aspx for the overload list.

I figured this out. The Stack Trace was misleading.
The issue was in building up the RowInfo object in my code... the RowID was a long and the variable that the property was setting it's value to was a decimal.
I believe the error occurred in the Sum call because of lazy loading where the setting of the attributes was not done until that call was made and the data was needed.

Related

Spring boot Postgres not return null when empty

I am using spring boot and spring data JPA with a Postgres database. There is a weird behaviour that happens when query something and the result is nothing.
In a lot of databases and projects when I make a query and the result was empty the returned object to java was null.
For example:
#Query(value = "select * from notification where WEBCODE = :webCode OR USERNAME = :username", nativeQuery = true)
Page<NotificationSQL> getNotificationsAsPage(#Param( "webCode" ) String webCode,#Param( "username" ) String username, Pageable pageable);
In this case I was suppose to get a null page. but in this case I am receiving an exception
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:259)
...
Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist: character varying = bytea
Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
Position: 42
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2552)
I do not understand why it does not just return a null object. It happens the same with the rest of the queries when empty rows and different objects as List classes. In a lot of projects this has not happen to me, the returned object when the query was right and empty rows was a null.
If the parameters are not null it works perfect, but the point is that these parameters sometimes are null and , as it can be seen in the image, the query works nice but with a result of empty rows.
Thanks in advance

Why do I get runtime error DBSQL_DBSL_LENGTH_ERROR?

I have the following code:
DATA: lt_matnr TYPE TABLE OF mara,
ls_matnr TYPE mara,
lv_werk TYPE werks_d VALUE 'WERK',
lt_stoc_int TYPE TABLE OF zmm_s_stock_list,
lt_stoc TYPE TABLE OF zsd_stock_list,
ls_stoc TYPE zsd_stock_list.
SELECT matnr
FROM mara
INTO CORRESPONDING FIELDS OF TABLE lt_matnr.
LOOP AT lt_matnr INTO ls_matnr.
CALL FUNCTION 'Z_MM_LIST_STOC_MATERIAL_WERKS'
EXPORTING
IP_MATNR = ls_matnr-matnr
IP_WERKS = lv_werk
IMPORTING
ET_STOCK_EXP = lt_stoc_int.
LOOP AT lt_stoc_int ASSIGNING FIELD-SYMBOL(<ls_stoc_int>).
MOVE-CORRESPONDING <ls_stoc_int> TO ls_stoc.
* + other data processing ...
APPEND ls_stoc TO lt_stoc.
ENDLOOP.
ENDLOOP.
INSERT zsd_stock_list FROM TABLE lt_stoc.
Everything works fine until the INSERT statement where I get the following short-dump:
Runtime error: DBSQL_DBSL_LENGTH_ERROR
Exception: CX_SY_OPEN_SQL_DB
Error analysis:
An exception has occurred which is explained in more detail below. The
exception, which is assigned to class 'CX_SY_OPEN_SQL_DB' was not caught an
therefore caused a runtime error. The reason for the exception is:
While accessing a database, the length of a field in ABAP does not
match the size of the corresponding database field.
This can happen for example if a string is bound to a database field
that is shorter than the current string.
It makes little sense because lt_stoc is TYPE TABLE OF zsd_stock_list, how can the field length not match ?

Handling Null DataType

I'm using the Over function from Piggybank to get the Lag of a row
res= foreach (group table by fieldA) {
Aord = order table by fieldB;
generate flatten(Stitch(Aord, Over(Aord.fieldB, 'lag'))) as (fieldA,fieldB,lag_fieldB) ;}
This works correctly and when I do a dump I get the expected result, the problem is when I want to use lag_fieldB for any comparison or transformation I get datatype issues.
If I do a describe it returns fieldA: long,fieldB: chararray,lag_fieldB: NULL
I'm new with PIG but I already tried casting to chararray and using ToString() and I keep getting errors like these:
ERROR 1052: Cannot cast bytearray to chararray
ERROR 1051: Cannot cast to bytearray
Thanks for your help
Ok after some looking around into the code of the Over function I found that you can instantiate the Over class to set the return type. What worked for me was:
DEFINE ChOver org.apache.pig.piggybank.evaluation.Over('chararray');
res= foreach (group table by fieldA) {
Aord = order table by fieldB;
generate flatten(Stitch(Aord, ChOver(Aord.fieldB, 'lag'))) as (fieldA,fieldB,lag_fieldB) ;}
Now the describe is telling me
fieldA: long,fieldB: chararray,lag_fieldB: chararray
And I'm able to use the columns as expected, hope this can save some time for someone else.

LINQ Statement in VB.Net - What is it doing?

I'm trying to understand what this LINQ statement is actually doing. I have no experience in LINQ, so I'm trying to get somewhat of a "plain english" translation.
MyDataTable contains the following data:
OrderByValues, Contract, PayType, PayAmount
Dim groupIDs = From r In myds.MyDataTable Select OBV = r.Item("OrderByValues"), PT = r.Item("PayType"), Contract = r("Contract") Distinct
For Each r in groupIDS
a = r.OBV
b = r.PT
c = r.Contract
Next
I'm not sure if there is enough info here to help you out or not. I'd appreciate any help.
Thanks.
The first line creates an query that will hold a collection of anonymous types. The query is not executed yet because of LINQ's deferred execution. This can be broken down into pieces:
From r In myds.MyDataTable defines r as an individual element of the IEnumerable (usually array or List)) myds.MyDataTable
Select OBV = r.Item("OrderByValues"), ... Distinct creates an anonymous type with properties called OBV, PT, Contract and assigns those properties values from the element r.
The foreach loop actually executes the query and creates the IEnumerable to iterate over. Then within this loop, it repeatedly sets a,b,c to the properties of the anonymous type defined in the query. This does seem a bit strange, since the variables a,b,c will only remember the last value set to them.
More reading on LINQ.
It selects all "OrderByValues", "PayType", and "Contract" columns from your datatable, ignoring duplicate rows.
It then iterates over the resultset, and assigns the 3 values to the variables "a", "b", and "c" respectively.

LINQ to SQL can't cast Int32 to String - how is that possible?

I'm getting this error
Unable to cast object of type 'System.Int32' to type 'System.String'.
when doing a routine LINQ to SQL query:
Return (
From n In DbContext.Newsletters
Where n.NewsletterID = NewsletterID
).FirstOrDefault
Here's the stack trace FWIW.
[InvalidCastException: Unable to cast object of type 'System.Int32' to type 'System.String'.]
System.Data.Linq.SqlClient.SqlProvider.Execute(Expression query, QueryInfo queryInfo, IObjectReaderFactory factory, Object[] parentArgs, Object[] userArgs, ICompiledSubQuery[] subQueries, Object lastResult) +1151
System.Data.Linq.SqlClient.SqlProvider.ExecuteAll(Expression query, QueryInfo[] queryInfos, IObjectReaderFactory factory, Object[] userArguments, ICompiledSubQuery[] subQueries) +113
System.Data.Linq.SqlClient.SqlProvider.System.Data.Linq.Provider.IProvider.Execute(Expression query) +344
System.Data.Linq.DataQuery`1.System.Linq.IQueryProvider.Execute(Expression expression) +56
System.Linq.Queryable.FirstOrDefault(IQueryable`1 source) +265
...
Two questions:
How is it possible that an Int32 can't be cast to String?
How can I debug something this? Since it all happens deep in the bowels of LINQ, I can't even get any indication what field this is angry about.
Possibly your entity mapping is incorrectly mapping an int to a string somewhere? Check the mapping for every property of Newsletters.
one of the 2:
either
Return (
From n In DbContext.Newsletters
Where n.NewsletterID = NewsletterID.ToString()
).FirstOrDefault
or
Return (
From n In DbContext.Newsletters
Where n.NewsletterID.ToString() = NewsletterID
).FirstOrDefault
BC those are mostlikely different types
Well, you can't cast a int to a string because the types are incompatible, but you can convert it. I suspect it's as simple as:
Return (
From n In DbContext.Newsletters
Where n.NewsletterID = int.Parse( NewsletterID )
).FirstOrDefault
Because the local variable is a string and the database column is an integer.
Int32 can't be cast to a String since they aren't at all the same type. You can convert an Int32 to a String via ToString, but there isn't a cast available.
From that simple statement, I would have to guess that n.NewsletterID and NewsletterID are not the same type. One needs to be converted to an Int32 or a String, e.g.
Return (
From n In DbContext.Newsletters
Where n.NewsletterID = NewsletterID.ToString(CultureInfo.InvariantCulture)
).FirstOrDefault
or, more likely
Return (
From n In DbContext.Newsletters
Where n.NewsletterID = Integer.Parse(NewsletterID, CultureInfo.InvariantCulture)
).FirstOrDefault
depending on which type is on each side of the expression.