Converting an index into a Sql column statement.

Sep 24, 2009 at 12:20 AM

I have a scenario where I would like the index into an array to translate into a column reference, as shown by the lines underlined.

var fieldQuery = from t in testCaseContext.TestCases
                 where t.Fields["Id"] == 1
                 select t;
SELECT TOP (1) t0.[TestCaseId], t0.[Area], t0.[Description]
FROM [vwTestCases] AS t1
LEFT OUTER JOIN [vwTitles] AS t2
  ON (t2.[Id] = t1.[TitleId])
LEFT OUTER JOIN [vwTestCaseTests] AS t0
  ON (t0.[TestCaseId] = t1.[Id])
WHERE (t1.[Id] = 1)

I currently have a CustomQueryFormatter that overrides VisitMethodCall and handles "get_Item". We then later handle the scenario in the VisitConstant function. But while handling the Expression's parameter, I noticed that I am having difficulty evaluating which table the converted parameter ("Id") would belong to. There are hacky ways of grabbing the column name from VisitSelect but definitely doesn't seem idea. So it seems I need another approach.

if (m.Object.Type == typeof(FieldDictionary))
    // User is trying to index into Fields
    switch (m.Method.Name)
        case "get_Item":

I am currently looking through the QueryBinder and trying to determine if I should handle VisitMethodCall in there and insert a DbExpression for the "get_Item" MethodCallExpression, to be evaluated properly later.

Ultimately, I'm just hoping to find the best approach to this problem. These linq queries will actually be fed into existing SQL statements as a Where clause, so the full IQToolkit generated string won't be used. The mapping to the Fields property doesn't need to be correct and I probably just need to leverage the ExpressionTree visiting functionality IQToolkit provides to generate that string.

Doesn't hurt to have the best approach though. Thanks for any help!

Sep 24, 2009 at 6:17 PM

If you look back in the expression to where the 't' was (it has since been translated), you'll find an EntityExpression node.  In here will be the MappingEntity argument you can use with the QueryMapping to determine the table.  Your best bet is to make the change in QueryBinder or in a new visitor sometime after QueryBinder, but one where you have access to the QueryMapping.  You can then convert the indexer call to a ColumnExpression.

Another solution would be to invent a new QueryMapping that would define specific properites like the 'Fields' collection as something that translates to column references.