SQL Generation Steps for OuterApply
See original GitHub issueHi,
Shorter version:
Found out today that Serenity picks OUTER APPLY
clause in its query builder before it goes for LEFT JOIN
values in XyzRow.cs
class, causing errors (there is a workaround causing more data reads than needed).
Longer version:
So in practical terms, if we have a LeftJoin
on a property in XyzRow.cs
class and want to use that left join in OuterApply
to limit data reads, Serenity throws a SQL error:
The multi-part identifier "jLeftJoinedTable.foreign_key_column" could not be bound.
That means, instead of generating a SQL with main tables and Property LeftJoins first e.g. the expected SQL would be:
SELECT * FROM [schema].[main_table] AS T0
LEFT JOIN [schema].[property_table] AS jLeftJoinedTable ON T0.foreign_key_column = jLeftJoinedTable.foreign_key_column
OUTER APPLY
(
SELECT DISTINCT
[outer_table].[column_id],
[outer_table].[column_name],
[outer_table].[effected_date]
FROM [schema].[some_other_table] AS [outer_table]
WHERE jLeftJoinedTable.outer_table_related_id = outer_table.id
)outerTable
The generated code for XyzRow.cs
class actually comes out as.
SELECT * FROM [schema].[main_table] AS T0
OUTER APPLY
(
SELECT DISTINCT
[outer_table].[column_id],
[outer_table].[column_name],
[outer_table].[effected_date]
FROM [schema].[some_other_table] AS [outer_table]
WHERE jLeftJoinedTable.outer_table_related_id = outer_table.id
)outerTable
LEFT JOIN [schema].[property_table] AS jLeftJoinedTable ON T0.foreign_key_column = jLeftJoinedTable.foreign_key_column
This causes The multi-part identifier
error mentioned above.
The workaround would be to force more data reads than necessary:
[OuterApply("outerTable", @"
SELECT DISTINCT
[outer_table].[column_id],
[outer_table].[column_name],
[outer_table].[effected_date]
FROM [schema].[some_other_table] AS [outer_table]
LEFT JOIN [schema].[a_third_table] AS [unnecessary_joined_table] ON outerTable.column = unnecessary_joined_table.column
LEFT JOIN [schema].[main_table] AS T1 ON a_third_table.some_column = T1.some_column
LEFT JOIN [schema].[property_table] AS jLeftJoinedTable ON T1.foreign_key_column = jLeftJoinedTable.foreign_key_column
WHERE jLeftJoinedTable.outer_table_related_id = outer_table.id
"])
// XyzRow code..
This makes for a painful SQL where we’d want just a setting label etc.
Interestingly, if we bypass List()
method of XyzRepository.cs
class and instead follow this:
[OuterApply("outerTable", @"
SELECT DISTINCT
[outer_table].[column_id],
[outer_table].[column_name],
[outer_table].[effected_date]
FROM [schema].[some_other_table] AS [outer_table]
WHERE jLeftJoinedTable.outer_table_related_id = outer_table.id
")]
// XyzRow code..
Then in XyzRepository.cs create a method:
List<XyzRow> CustomListMethod()
{
// Get latest by create datetime descending.
void action(SqlQuery query)
{
query.Distinct(true);
query.SelectTableFields();
query.SelectNonTableFields();
// query.DebugText.Dump("--List OuContractWeeklyActivityEventRow"); <= checked in LINQPad 6
//query.ToString().Dump("--GetOUsByPostAssignment");
}
List<XyzRow> rows = null;
using (var connection = SqlConnections.NewByKey(fld.ConnectionKey))
{
rows = connection.List<XyzRow>(action);
}
return rows;
}
// XyzRepository code...
Then the SQL is correctly generated as:
SELECT * FROM [schema].[main_table] AS T0
LEFT JOIN [schema].[property_table] AS jLeftJoinedTable ON T0.foreign_key_column = jLeftJoinedTable.foreign_key_column
OUTER APPLY
(
SELECT DISTINCT
[outer_table].[column_id],
[outer_table].[column_name],
[outer_table].[effected_date]
FROM [schema].[some_other_table] AS [outer_table]
WHERE jLeftJoinedTable.outer_table_related_id = outer_table.id
)outerTable
Please can this be looked into? Will save us from creating unnecessary CustomList()
methods in repositories.
Kind Regards.
Issue Analytics
- State:
- Created 3 years ago
- Reactions:1
- Comments:7 (5 by maintainers)
Please check this commit with a row similar to yours and the test for it:
https://github.com/volkanceylan/Serenity/commit/875fd6dc9c9493ab3b2ecfbcc7401cef227b933d
I got expected results with your outer apply statement. Need to identify what is different with your row.
If your issue is about order, then select a column in left joined table so that the join is included in query before outer apply.