EntitySpaces/C#: Как использовать подзапрос в операторе CASE?

Я пытаюсь эмулировать фрагмент SQL с помощью EntitySpaces. Я почти готов вернуться к хорошему старому сырому SQL, но лучше научусь делать это правильно...

Это SQL, который я пытаюсь воспроизвести:

SELECT 
    CASE WHEN GL.SOURCE = 'AP' THEN (SELECT COMPANY FROM VEND WHERE VEND.ID = GL.ID)
        WHEN GL.SOURCE = 'AR' THEN (SELECT COMPANY FROM CUST WHERE CUST.ID = GL.ID)
        WHEN GL.SOURCE = 'SB' THEN (SELECT COMPANY FROM SBMASTER WHERE SBMASTER.ID = GL.ID)
        ELSE '' END AS COMPANY
FROM GL
    LEFT OUTER JOIN ACCT ON GL.ACCT = ACCT.ACCT

Я немного поигрался с кодом без удачи. Вот что у меня есть на данный момент:

    GlQuery qryGl = new GlQuery("qryGl");
    AcctQuery qryAcct = new AcctQuery("qryAcct");
    AcctQuery qryAcctSub = new AcctQuery("qryAcct");
    VendQuery qryVendSub = new VendQuery("qryVend");
    CustQuery qryCustSub = new CustQuery("qryCust");
    SbmasterQuery qrySbmasterSub = new SbmasterQuery("qrySbmaster");

    qryGl.Select
    (
        qryGl.Source.Case()
            .When("AP").Then(qryVendSub.Select(qryVendSub.Company).Where(qryVendSub.Id == qryGl.Id))
            .When("AR").Then(qryCustSub.Select(qryCustSub.Company).Where(qryCustSub.Id == qryGl.Id))
            .When("SB").Then(qrySbmasterSub.Select(qrySbmasterSub.Company).Where(qrySbmasterSub.Id == qryGl.Id))
            .Else("")
            .End().As("COMPANY")
    );
    qryGl.LeftJoin(qryAcct).On(qryGl.Acct == qryAcct.Acct);

что дает мне следующий (явно неправильный!) вывод:

SELECT 
    [COMPANY] = CASE  
        WHEN 'AP' THEN MyProject.Com.Data.VendQuery 
        WHEN 'AR' THEN MyProject.Com.Data.CustQuery 
        WHEN 'SB' THEN MyProject.Com.Data.SbmasterQuery 
        ELSE '' 
    END   
FROM [GL] qryGl 
    LEFT JOIN [ACCT] qryAcct ON qryGl.[ACCT] = qryAcct.[ACCT]

Буду признателен за любую помощь в получении этого подзапроса SQL в оператор case!

Довольно плохо знаком с EntitySpaces, так что надеюсь, что это просто что-то простое, что я пропустил...

ура

1 ответ

Решение

Рассматривая методы, доступные для Then() метод, я думаю, что это не возможно.

  1. E сть Then(object), к которому относится ваш запрос, и EntitySpaces преобразует его в строковый литерал и помещает его непосредственно в окончательный запрос.
  2. E сть Then(esQueryItem) который будет работать с одним столбцом, таким как qryGl.Source,
  3. Наконец, есть Then(esExpression), Я немного запутался в этом, но я думаю, что он используется для размещения параметров выбора операторов, так что, вероятно, он тоже не будет работать для вас.

Я думаю, что вам нужно это Then(DynamicQuery) или что-то подобное.

Поскольку EntitySpaces является открытым исходным кодом, теперь вы можете добавить эту перегрузку самостоятельно, а затем изменить поставщиков данных, которые вы используете, для работы с новой опцией подзапроса. Я сделал аналогичное изменение для обработки подзапросов в других местах, и это было не так уж плохо для задачи. Самой простой частью на самом деле являются провайдеры, потому что, как только вы определите, что имеете дело с подзапросом, вам, по сути, нужно только снова вызвать вершину стека для вашего нового встроенного запроса, прежде чем продолжить.

Однако из того, что я видел выше, я бы сказал, что если вы хотите избежать взлома кода EntitySpaces, вам, вероятно, придется обратиться к жестко закодированному запросу. Майк из EntitySpaces всегда рекомендовал просмотр базы данных или хранимую процедуру для таких пользовательских загрузок.

Также: имейте в виду, что если вы создаете ручные запросы на стороне клиента, вы все равно можете избежать жесткого кодирования большей части запроса, используя [TableName]Metadata.ColumnNames.[ColumnNameConstant].

Другие вопросы по тегам