Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EF Core invalid generated query #349

Open
tomasfil opened this issue May 6, 2024 · 4 comments
Open

EF Core invalid generated query #349

tomasfil opened this issue May 6, 2024 · 4 comments
Assignees

Comments

@tomasfil
Copy link

tomasfil commented May 6, 2024

Hello, I have come across bug with EF Core Linq to entities.
This query:

Query
    .Select(s=> new ValueSet<JobLine, List<ValueSet<Transaction, List<string>>>>
    {
        Value1 = s,
        Value2 =s.Transactions!.Select(x=>
        new ValueSet<Transaction, List<string>>
        {
            Value1 = x,
            Value2 = x.PairStatuses!
                                .Where(ps => (x.CreatedDate > ps.StartDate && x.CreatedDate < ps.EndDate) || (x.UpdatedDate > ps.StartDate && x.UpdatedDate < ps.EndDate))
                                .Select(s => s.User!.FullName)
                                .ToList()
        }).ToList()
    })
    .Where(jl => jl.CaseNo == caseNo)
    .Include(x => x.JobLineItems!)
    .ThenInclude(x => x.EbsItem!)
    .Include(x => x.JobHeader!)
    .ThenInclude(x => x.RequestType!)
    .Include(x=>x.Transactions!)
    .ThenInclude(x => x.TransactionItems)
    .AsNoTrackingWithIdentityResolution();

Results into this sql

SELECT "t"."ID", "t"."ATTRIBUTE1", "t"."ATTRIBUTE2", "t"."ATTRIBUTE3", "t"."ATTRIBUTE4", "t"."ATTRIBUTE5", "t"."ATTRIBUTE6", "t"."CASE_NO", "t"."CREATED_BY", "t"."CREATED_DATE", "t"."FROM_INVENTORY", "t"."FROM_LOCATOR", "t"."JOB_HEADER_ID", "t"."MACHINE_ID", "t"."PICKING_ORDER", "t"."PRINTED", "t"."ROUTING_ID", "t"."SOURCE_LINE_ID", "t"."STATUS", "t"."TO_INVENTORY", "t"."TO_LOCATOR", "t"."UPDATED_BY", "t"."UPDATED_DATE", "t"."VALID", "t"."WINDOWS_USER", "t0"."ID", "v"."ID", "t1"."ID", "t1"."APP_ID", "t1"."APPL_REV", "t1"."ATTRIBUTE1", "t1"."ATTRIBUTE2", "t1"."ATTRIBUTE3", "t1"."ATTRIBUTE4", "t1"."ATTRIBUTE5", "t1"."ATTRIBUTE6", "t1"."CONTENT_ID", "t1"."CREATED_BY", "t1"."CREATED_DATE", "t1"."DEVICE_IP", "t1"."INVENTORY_ITEM_ID", "t1"."ITEM", "t1"."JOB_LINE_ID", "t1"."LOT_NO", "t1"."QUANTITY", "t1"."SHIPPING_QUANTITY", "t1"."SOURCE_LINE_ITEM_ID", "t1"."UOM", "t1"."UPDATED_BY", "t1"."UPDATED_DATE", "t1"."VALID", "t1"."VENDOR_LOT_NO", "t1"."WINDOWS_USER", "t1"."ID0", "t1"."BUILD_IN_WIP_FLAG", "t1"."CLASS", "t1"."DESCRIPTION", "t1"."EXPIRATION_DAYS", "t1"."FIXED_LOT_MULTIPLIER", "t1"."INITIAL_GOKI", "t1"."INVENTORY_ITEM_STATUS_CODE", "t1"."ITEM0", "t1"."ITEM_NO", "t1"."ITM_CREATED_BY", "t1"."ITM_CREATION_DATE", "t1"."ITM_UPDATE_DATE", "t1"."ITM_UPDATED_BY", "t1"."MTL_TRANSACTIONS_ENABLED_FLAG", "t1"."PRD_CD", "t1"."RECEIVING_ROUTING_ID", "t1"."RECEIVING_ROUTING_NM", "t1"."SHIPPING", "t1"."STOCK_ENABLED_FLAG", "t1"."UOM_CD", "t1"."WEIGHT", "t0"."ATTRIBUTE1", "t0"."ATTRIBUTE2", "t0"."ATTRIBUTE3", "t0"."ATTRIBUTE4", "t0"."ATTRIBUTE5", "t0"."ATTRIBUTE6", "t0"."CREATED_BY", "t0"."CREATED_DATE", "t0"."DIRECTION_FLG", "t0"."DOC_NAME", "t0"."IMPORTED_BY", "t0"."IMPORTED_DATE", "t0"."JOB_TYPE", "t0"."MARKED", "t0"."NEED_TO_DATE", "t0"."NOTE", "t0"."PL_LAST_PRINT_DATE", "t0"."PL_PRINT_COUNT", "t0"."PRIORITY", "t0"."REQUEST_TYPE_ID", "t0"."SOURCE", "t0"."SOURCE_HEADER_ID", "t0"."SOURCE_NAME", "t0"."STATUS", "t0"."UPDATED_BY", "t0"."UPDATED_DATE", "t0"."VALID", "v"."ATTRIBUTE1", "v"."ATTRIBUTE2", "v"."ATTRIBUTE3", "v"."ATTRIBUTE4", "v"."ATTRIBUTE5", "v"."ATTRIBUTE6", "v"."COL_ORDER", "v"."CREATED_BY", "v"."CREATED_DATE", "v"."DESTINATION_PARTY_ID", "v"."PAIR_TRX", "v"."REC_NUM", "v"."REQUEST_DESC", "v"."REQUEST_TYPE_FLOW", "v"."SOURCE_PARTY_ID", "v"."TRX_MATERIAL_TYPE", "v"."UPDATED_BY", "v"."UPDATED_DATE", "v"."VALID", "t3"."ID", "t3"."APP_ID", "t3"."APPL_REV", "t3"."ATTRIBUTE1", "t3"."ATTRIBUTE2", "t3"."ATTRIBUTE3", "t3"."ATTRIBUTE4", "t3"."ATTRIBUTE5", "t3"."ATTRIBUTE6", "t3"."CASE_NO", "t3"."CODE_TEXT", "t3"."CREATED_BY", "t3"."CREATED_DATE", "t3"."DEVICE_IP", "t3"."ERP_INTERFACED", "t3"."FROM_ACCOUNT", "t3"."FROM_ACCOUNT_ID", "t3"."FROM_INVENTORY", "t3"."FROM_LOCATOR", "t3"."FROM_LOCATOR_ID", "t3"."JOB_LINE_ID", "t3"."LABEL_ID", "t3"."MACHINE_ID", "t3"."TO_ACCOUNT", "t3"."TO_ACCOUNT_ID", "t3"."TO_INVENTORY", "t3"."TO_LOCATOR", "t3"."TO_LOCATOR_ID", "t3"."TRX_TYPE_ID", "t3"."UPDATED_BY", "t3"."UPDATED_DATE", "t3"."VALID", "t3"."WINDOWS_USER", "t3"."ID0", "t3"."APP_ID0", "t3"."APPL_REV0", "t3"."ATTRIBUTE10", "t3"."ATTRIBUTE20", "t3"."ATTRIBUTE30", "t3"."ATTRIBUTE40", "t3"."ATTRIBUTE50", "t3"."ATTRIBUTE60", "t3"."CONTENT_ID", "t3"."CREATED_BY0", "t3"."CREATED_DATE0", "t3"."DEVICE_IP0", "t3"."ERP_INTERFACE_ID", "t3"."INVENTORY_ITEM_ID", "t3"."ITEM", "t3"."LOT_NO", "t3"."QUANTITY", "t3"."SOURCE_TRX_ITEM_ID", "t3"."TRX_ID", "t3"."UOM", "t3"."UPDATED_BY0", "t3"."UPDATED_DATE0", "t3"."VALID0", "t3"."VENDOR_LOT_NO", "t3"."WINDOWS_USER0", "t6"."ID", "t6"."APP_ID", "t6"."APPL_REV", "t6"."ATTRIBUTE1", "t6"."ATTRIBUTE2", "t6"."ATTRIBUTE3", "t6"."ATTRIBUTE4", "t6"."ATTRIBUTE5", "t6"."ATTRIBUTE6", "t6"."CASE_NO", "t6"."CODE_TEXT", "t6"."CREATED_BY", "t6"."CREATED_DATE", "t6"."DEVICE_IP", "t6"."ERP_INTERFACED", "t6"."FROM_ACCOUNT", "t6"."FROM_ACCOUNT_ID", "t6"."FROM_INVENTORY", "t6"."FROM_LOCATOR", "t6"."FROM_LOCATOR_ID", "t6"."JOB_LINE_ID", "t6"."LABEL_ID", "t6"."MACHINE_ID", "t6"."TO_ACCOUNT", "t6"."TO_ACCOUNT_ID", "t6"."TO_INVENTORY", "t6"."TO_LOCATOR", "t6"."TO_LOCATOR_ID", "t6"."TRX_TYPE_ID", "t6"."UPDATED_BY", "t6"."UPDATED_DATE", "t6"."VALID", "t6"."WINDOWS_USER", "t6"."ID0", "t6"."APP_ID0", "t6"."APPL_REV0", "t6"."ATTRIBUTE10", "t6"."ATTRIBUTE20", "t6"."ATTRIBUTE30", "t6"."ATTRIBUTE40", "t6"."ATTRIBUTE50", "t6"."ATTRIBUTE60", "t6"."CONTENT_ID", "t6"."CREATED_BY0", "t6"."CREATED_DATE0", "t6"."DEVICE_IP0", "t6"."ERP_INTERFACE_ID", "t6"."INVENTORY_ITEM_ID", "t6"."ITEM", "t6"."LOT_NO", "t6"."QUANTITY", "t6"."SOURCE_TRX_ITEM_ID", "t6"."TRX_ID", "t6"."UOM", "t6"."UPDATED_BY0", "t6"."UPDATED_DATE0", "t6"."VALID0", "t6"."VENDOR_LOT_NO", "t6"."WINDOWS_USER0", "t6"."FULL_NAME", "t6"."ID1", "t6"."ID00"
      FROM "WMS"."T_JOB_LINES" "t"
      LEFT JOIN "WMS"."T_JOB_HEADERS" "t0" ON ("t"."JOB_HEADER_ID" = "t0"."ID")
      LEFT JOIN "WMS"."V_REQUEST_TYPE" "v" ON ("t0"."REQUEST_TYPE_ID" = "v"."ID")
      LEFT JOIN (
          SELECT "t2"."ID", "t2"."APP_ID", "t2"."APPL_REV", "t2"."ATTRIBUTE1", "t2"."ATTRIBUTE2", "t2"."ATTRIBUTE3", "t2"."ATTRIBUTE4", "t2"."ATTRIBUTE5", "t2"."ATTRIBUTE6", "t2"."CONTENT_ID", "t2"."CREATED_BY", "t2"."CREATED_DATE", "t2"."DEVICE_IP", "t2"."INVENTORY_ITEM_ID", "t2"."ITEM", "t2"."JOB_LINE_ID", "t2"."LOT_NO", "t2"."QUANTITY", "t2"."SHIPPING_QUANTITY", "t2"."SOURCE_LINE_ITEM_ID", "t2"."UOM", "t2"."UPDATED_BY", "t2"."UPDATED_DATE", "t2"."VALID", "t2"."VENDOR_LOT_NO", "t2"."WINDOWS_USER", "v0"."ID" "ID0", "v0"."BUILD_IN_WIP_FLAG", "v0"."CLASS", "v0"."DESCRIPTION", "v0"."EXPIRATION_DAYS", "v0"."FIXED_LOT_MULTIPLIER", "v0"."INITIAL_GOKI", "v0"."INVENTORY_ITEM_STATUS_CODE", "v0"."ITEM" "ITEM0", "v0"."ITEM_NO", "v0"."ITM_CREATED_BY", "v0"."ITM_CREATION_DATE", "v0"."ITM_UPDATE_DATE", "v0"."ITM_UPDATED_BY", "v0"."MTL_TRANSACTIONS_ENABLED_FLAG", "v0"."PRD_CD", "v0"."RECEIVING_ROUTING_ID", "v0"."RECEIVING_ROUTING_NM", "v0"."SHIPPING", "v0"."STOCK_ENABLED_FLAG", "v0"."UOM_CD", "v0"."WEIGHT"
          FROM "WMS"."T_JOB_LINES_ITEM" "t2"
          LEFT JOIN "WMS"."V_EBS_ITEM" "v0" ON ("t2"."INVENTORY_ITEM_ID" = "v0"."ID")
      ) "t1" ON ("t"."ID" = "t1"."JOB_LINE_ID")
      LEFT JOIN (
          SELECT "t4"."ID", "t4"."APP_ID", "t4"."APPL_REV", "t4"."ATTRIBUTE1", "t4"."ATTRIBUTE2", "t4"."ATTRIBUTE3", "t4"."ATTRIBUTE4", "t4"."ATTRIBUTE5", "t4"."ATTRIBUTE6", "t4"."CASE_NO", "t4"."CODE_TEXT", "t4"."CREATED_BY", "t4"."CREATED_DATE", "t4"."DEVICE_IP", "t4"."ERP_INTERFACED", "t4"."FROM_ACCOUNT", "t4"."FROM_ACCOUNT_ID", "t4"."FROM_INVENTORY", "t4"."FROM_LOCATOR", "t4"."FROM_LOCATOR_ID", "t4"."JOB_LINE_ID", "t4"."LABEL_ID", "t4"."MACHINE_ID", "t4"."TO_ACCOUNT", "t4"."TO_ACCOUNT_ID", "t4"."TO_INVENTORY", "t4"."TO_LOCATOR", "t4"."TO_LOCATOR_ID", "t4"."TRX_TYPE_ID", "t4"."UPDATED_BY", "t4"."UPDATED_DATE", "t4"."VALID", "t4"."WINDOWS_USER", "t5"."ID" "ID0", "t5"."APP_ID" "APP_ID0", "t5"."APPL_REV" "APPL_REV0", "t5"."ATTRIBUTE1" "ATTRIBUTE10", "t5"."ATTRIBUTE2" "ATTRIBUTE20", "t5"."ATTRIBUTE3" "ATTRIBUTE30", "t5"."ATTRIBUTE4" "ATTRIBUTE40", "t5"."ATTRIBUTE5" "ATTRIBUTE50", "t5"."ATTRIBUTE6" "ATTRIBUTE60", "t5"."CONTENT_ID", "t5"."CREATED_BY" "CREATED_BY0", "t5"."CREATED_DATE" "CREATED_DATE0", "t5"."DEVICE_IP" "DEVICE_IP0", "t5"."ERP_INTERFACE_ID", "t5"."INVENTORY_ITEM_ID", "t5"."ITEM", "t5"."LOT_NO", "t5"."QUANTITY", "t5"."SOURCE_TRX_ITEM_ID", "t5"."TRX_ID", "t5"."UOM", "t5"."UPDATED_BY" "UPDATED_BY0", "t5"."UPDATED_DATE" "UPDATED_DATE0", "t5"."VALID" "VALID0", "t5"."VENDOR_LOT_NO", "t5"."WINDOWS_USER" "WINDOWS_USER0"
          FROM "WMS"."T_TRX" "t4"
          LEFT JOIN "WMS"."T_TRX_ITEM" "t5" ON ("t4"."ID" = "t5"."TRX_ID")
      ) "t3" ON ("t"."ID" = "t3"."JOB_LINE_ID")
      LEFT JOIN (
          SELECT "t7"."ID", "t7"."APP_ID", "t7"."APPL_REV", "t7"."ATTRIBUTE1", "t7"."ATTRIBUTE2", "t7"."ATTRIBUTE3", "t7"."ATTRIBUTE4", "t7"."ATTRIBUTE5", "t7"."ATTRIBUTE6", "t7"."CASE_NO", "t7"."CODE_TEXT", "t7"."CREATED_BY", "t7"."CREATED_DATE", "t7"."DEVICE_IP", "t7"."ERP_INTERFACED", "t7"."FROM_ACCOUNT", "t7"."FROM_ACCOUNT_ID", "t7"."FROM_INVENTORY", "t7"."FROM_LOCATOR", "t7"."FROM_LOCATOR_ID", "t7"."JOB_LINE_ID", "t7"."LABEL_ID", "t7"."MACHINE_ID", "t7"."TO_ACCOUNT", "t7"."TO_ACCOUNT_ID", "t7"."TO_INVENTORY", "t7"."TO_LOCATOR", "t7"."TO_LOCATOR_ID", "t7"."TRX_TYPE_ID", "t7"."UPDATED_BY", "t7"."UPDATED_DATE", "t7"."VALID", "t7"."WINDOWS_USER", "t8"."ID" "ID0", "t8"."APP_ID" "APP_ID0", "t8"."APPL_REV" "APPL_REV0", "t8"."ATTRIBUTE1" "ATTRIBUTE10", "t8"."ATTRIBUTE2" "ATTRIBUTE20", "t8"."ATTRIBUTE3" "ATTRIBUTE30", "t8"."ATTRIBUTE4" "ATTRIBUTE40", "t8"."ATTRIBUTE5" "ATTRIBUTE50", "t8"."ATTRIBUTE6" "ATTRIBUTE60", "t8"."CONTENT_ID", "t8"."CREATED_BY" "CREATED_BY0", "t8"."CREATED_DATE" "CREATED_DATE0", "t8"."DEVICE_IP" "DEVICE_IP0", "t8"."ERP_INTERFACE_ID", "t8"."INVENTORY_ITEM_ID", "t8"."ITEM", "t8"."LOT_NO", "t8"."QUANTITY", "t8"."SOURCE_TRX_ITEM_ID", "t8"."TRX_ID", "t8"."UOM", "t8"."UPDATED_BY" "UPDATED_BY0", "t8"."UPDATED_DATE" "UPDATED_DATE0", "t8"."VALID" "VALID0", "t8"."VENDOR_LOT_NO", "t8"."WINDOWS_USER" "WINDOWS_USER0", "t9"."FULL_NAME", "t9"."ID" "ID1", "t9"."ID0" "ID00"
          FROM "WMS"."T_TRX" "t7"
          LEFT JOIN "WMS"."T_TRX_ITEM" "t8" ON ("t7"."ID" = "t8"."TRX_ID")
          OUTER APPLY (
              SELECT "t11"."FULL_NAME", "t10"."ID", "t11"."ID" "ID0"
              FROM "WMS"."T_PAIR_STATUS" "t10"
              LEFT JOIN "WMS"."T_USERS" "t11" ON ("t10"."USER_ID" = "t11"."ID")
              WHERE (((("t7"."MACHINE_ID" = "t10"."MACHINE_ID")) AND (((((((("t7"."CREATED_DATE" > "t10"."START_DATE")) AND (("t7"."CREATED_DATE" < "t10"."END_DATE"))))) OR ((((("t7"."UPDATED_DATE" > "t10"."START_DATE")) AND (("t7"."UPDATED_DATE" < "t10"."END_DATE"))))))))))
          ) "t9"
      ) "t6" ON ("t"."ID" = "t6"."JOB_LINE_ID")
      WHERE ("t"."CASE_NO" = :caseNo_0)

      ORDER BY "t"."ID", "t0"."ID", "v"."ID", "t1"."ID", "t1"."ID0", "t3"."ID", "t3"."ID0", "t6"."ID", "t6"."ID0", "t6"."ID1"

And that fails on:

OracleExecutionStrategy.ExecuteAsync() :  Oracle.ManagedDataAccess.Client.OracleException (0x80004005): ORA-00907: missing right parenthesis
         at OracleInternal.ServiceObjects.OracleConnectionImpl.VerifyExecution(Int32& cursorId, Boolean bThrowArrayBindRelatedErrors, SqlStatementType sqlStatementType, Int32 arrayBindCount, OracleException& exceptionForArrayBindDML, Boolean& hasMoreRowsInDB, Boolean bFirstIterationDone)
         at OracleInternal.ServiceObjects.OracleCommandImpl.ExecuteReader(String commandText, OracleParameterCollection paramColl, CommandType commandType, OracleConnectionImpl connectionImpl, OracleDataReaderImpl& rdrImpl, Int32 longFetchSize, Int64 clientInitialLOBFS, OracleDependencyImpl orclDependencyImpl, Int64[] scnForExecution, Int64[]& scnFromExecution, OracleParameterCollection& bindByPositionParamColl, Boolean& bBindParamPresent, Int64& internalInitialLOBFS, Int64 internalInitialJSONFS, OracleException& exceptionForArrayBindDML, OracleConnection connection, IEnumerable`1 adrianParsedStmt, Boolean isDescribeOnly, Boolean isFromEF)
         at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteReader(Boolean requery, Boolean fillRequest, CommandBehavior behavior)
         at Oracle.ManagedDataAccess.Client.OracleCommand.ExecuteDbDataReader(CommandBehavior behavior)
         at System.Data.Common.DbCommand.ExecuteDbDataReaderAsync(CommandBehavior behavior, CancellationToken cancellationToken)
      --- End of stack trace from previous location ---
         at Oracle.EntityFrameworkCore.Storage.Internal.OracleRelationalCommandBuilderFactory.OracleRelationalCommandBuilder.OracleRelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
         at Oracle.EntityFrameworkCore.Storage.Internal.OracleRelationalCommandBuilderFactory.OracleRelationalCommandBuilder.OracleRelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
         at Oracle.EntityFrameworkCore.Storage.Internal.OracleRelationalCommandBuilderFactory.OracleRelationalCommandBuilder.OracleRelationalCommand.ExecuteReaderAsync(RelationalCommandParameterObject parameterObject, CancellationToken cancellationToken)
         at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.AsyncEnumerator.InitializeReaderAsync(AsyncEnumerator enumerator, CancellationToken cancellationToken)
         at Oracle.EntityFrameworkCore.Storage.Internal.OracleExecutionStrategy.ExecuteAsync[TState,TResult](TState state, Func`4 operation, Func`4 verifySucceeded, CancellationToken cancellationToken)

System info:
Oracle 11.2g
.NET 7
Oracle.EntityFrameworkCore 7.21.13

This is not the first time that this parenthesis bug arrived. I have simulated the same complex query with MSSQL and Postgre and both work. You should add some kind of unit test to test the generated queries especially for the parenthesis.

@tomasfil
Copy link
Author

tomasfil commented May 6, 2024

The issues is definetly the select. Same reproduces directly on table only with select without includes:

 Query.Select(s =>
 new ValueSet<decimal, IEnumerable<string>>
 {
     Value1 = s.Id,
     Value2 = s.PairStatuses!.Where(ps =>
         (s.CreatedDate > ps.StartDate && s.CreatedDate < ps.EndDate) || (s.UpdatedDate > ps.StartDate && s.UpdatedDate < ps.EndDate))
     .Select(s => s.User!.FullName)
 })
     .Where(x=> transactionIds.Contains(x.Id))

@alexkeh
Copy link
Contributor

alexkeh commented May 6, 2024

@tomasfil Does this problem occur with DB 19c or higher? Oracle DB 11.2 is no longer supported. ODP.NET no longer tests nor fixes bugs against DB 11.2 except under rare circumstances.

If so, can you provide a complete EF Core test case? We'll try to reproduce the issue in in house and fix it if we identify an ODP.NET code problem.

Of note, MS ends EF Core 7 support next week. Oracle plans to desupport EF Core 7 at the same time.

@tomasfil
Copy link
Author

I will try and provide simple test case soon.

@alexkeh
Copy link
Contributor

alexkeh commented May 13, 2024

Providing a test case may be moot if this bug doesn't occur with Oracle DB 19c or higher. The ODP.NET team doesn't plan to implement bug fixes for out of support DB versions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants