Query: element access on a collection of primitives parameter throws bad exception when run on sql server that doesn't support JSON
Scenario:
string[] values = new[] { "one", "two", "three", "four" };
return AssertQuery(
async,
ss => from e in ss.Set<PrimitiveCollectionsEntity>()
let value = e.Id > 0 && e.Id < 4 ? values[e.Id] : "zero"
select new { e.Id, value });
when ran in the "legacy" mode, we throw
Unable to cast object of type 'System.String[]' to type 'System.Linq.IQueryable`1[System.String]'.
Here is the shaper that we generate:
(queryContext, dataReader, resultContext, resultCoordinator) =>
{
int? value1;
bool? value2;
IQueryable<string> value3;
int? value4;
value1 = (int?)dataReader.GetInt32(0);
value2 = dataReader.IsDBNull(1) ? default(bool?) : (bool?)dataReader.GetBoolean(1);
value3 = dataReader.IsDBNull(2) ? default(IQueryable<string>) : (IQueryable<string>)(IEnumerable<string>)new JsonCollectionOfReferencesReaderWriter<string[], string>(JsonStringReaderWriter.Instance).FromJsonString(
json: (string)dataReader.GetFieldValue<object>(2),
existingObject: null);
value4 = (int?)dataReader.GetInt32(0);
return new {
Id = (int)value1,
value = value2 == True ? value3
.ElementAt((int)value4) : "zero"
};
}
and here is the sql:
exec sp_executesql N'SELECT [p].[Id], CASE
WHEN [p].[Id] > 0 AND [p].[Id] < 4 THEN CAST(1 AS bit)
ELSE CAST(0 AS bit)
END, @__values_0
FROM [PrimitiveCollectionsEntity] AS [p]',N'@__values_0 nvarchar(4000)',@__values_0=N'["one","two","three","four"]'
values parameter is array of strings, and we do read it as IEnumerable
In preprocessing we normalize indexer over parameter array into:
[ParameterQueryRootExpression].AsQueryable().ElementAt(...), then nav expansion gobbles up AsQueryable call (because in normal mode this all will get translated, so AsQueryable is not necessary). In legacy mode we end up client-evaling the whole thing, but we don't restore AsQueryable or apply original indexer or Enumerable.ElementAt.
FYI @roji This might go away if/when we get rid of nav expansion, also low priority bug, only happens in legacy mode and test case seems uncommon