none
ASP[VB].NET Использование функций из модуля в SQL-запросах RRS feed

  • Вопрос

  • Переношу программную часть одной системы из MS Access в среду ASP.NET. Столкнулся с такой вот проблемой. В Access в модуле есть функции:

    Public Function Hour2Min(Hours)
    Dim ErrLoop As Error, strError As String
    On Error GoTo Err_Sub
    
    If NZ(Hours) <> "" Then
        Hour2Min = (((NZ(Hours) * 100) \ 100) * 60) + (NZ(Hours) * 100) Mod 100
    End If
    Exit Function
    Exit_Sub:
        Exit Function
    Err_Sub:
        For Each ErrLoop In Errors
            With ErrLoop
                strError = "Ошибка #" & .Number & vbCr
                strError = strError & "    " & .Description & vbCr
            End With
            MsgBox strError & " Или файл не читается.", vbExclamation
        Next
        Resume Exit_Sub
    
    End Function

    и

    Function Dat_ymdhn(dat2)
        Dat_ymdhn = IIf(IsNull(dat2), 0, Format(dat2, "yyyymmddhhnn"))
    End Function

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

    Но теперь возникла проблема, в Access в нескольких местах на переносимой форме делаются запросы к базе данных, а в самих запросах идет вызов этих самых функций. Я специально проверял - на используемой базе данных хранимых процедур с этим именем не существует, по словам всех разработчиков, которые пишут у нас систему на Access - в SQL запросах спокойно обрабатываются функции из модулей. Однако, ASP.NET говорит, что таких функций нет и отказывается обрабатывать эту часть кода. Может я еще что не так перенес? В Access  используется специальный тип данных для запросов

    Set rst20 = CurrentDb.OpenRecordset("Select Sum(Hour2Min(VR_POL))/90 as M_Nalet, Sum(N2PC)/90 as M_Land, " _
        & "Sum(IIF(Max_Nad_GK=0,0,1))/90 as M_Nadduv, Sum(Kol_RVPP)/90 as M_RVPP " _
        & "From Param_Pol_VZL_M WHERE BN = '" & Bort & "' AND Dat_ymdhn(Data_VR_VIL) > " _
        & Dat_ymdhn(DateAdd("y", -90, Now)), dbOpenSnapshot)

    На ASP.NET я же это перенес созданием AccessDataSource и заданием ему комманды Select и обращением к базе данных.

    rst20_Source.SelectCommand = "select sum(Hour2Min(VR_POL))/90 as m_nalet, sum(n2pc)/90 as m_land, " _
           & "sum(iif(max_nad_gk=0,0,1))/90 as m_nadduv, sum(kol_rvpp)/90 as m_rvpp " _
           & "from param_pol_vzl_m where bn = '" & BN.Text & "' and Dat_ymdhn(data_vr_vil) > '" _
           & DateAdd("y", -90, Now) & "'"
            rst20 = CType(rst20_Source.Select(DataSourceSelectArguments.Empty)(0), DataRowView)
    

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

    9 апреля 2012 г. 7:12

Ответы

  • В итоге - так и не нашел подобный метод. Знакомые дали наводку на LINQ, мол через него можно сделать, но попытки вставить функции в Select или Where не увенчались успехом. На данный момент имею следующий полностью рабочий и уже используемый код:

    Dim rst20 = From fields In db.PARAM_POL_VZL_M _
                      Where fields.BN = BN.Text And fields.DATA_VR_VIL > DateAdd("y", -90, Now()) _
                      Select fields.VR_POL, fields.N2PC, fields.MAX_NAD_GK, fields.KOL_RVPP
    
    
            For Each row In rst20
                If row.VR_POL.HasValue Then m_nalet = m_nalet + Hour2Min(row.VR_POL)
                If row.N2PC.HasValue Then m_land = m_land + row.N2PC
                If row.MAX_NAD_GK.HasValue Then m_nadduv = m_nadduv + IIf(row.MAX_NAD_GK = 0, 0, 1) / 90
                If row.KOL_RVPP.HasValue Then m_rvpp = m_rvpp + row.KOL_RVPP
            Next
            m_nalet = m_nalet / 90
            m_land = m_land / 90
            m_nadduv = m_nadduv / 90
            m_rvpp = m_rvpp / 90
    Но все равно, буду признателен, если кто хотя бы в LINQ расскажет как вставлять функции\использовать оператор, а то угнетает ,что в Access это занимает 2 строки запроса, а в ASP.NET добавляет к запросу 10 дополнительных строк.

    11 апреля 2012 г. 12:30

Все ответы

  • В итоге - так и не нашел подобный метод. Знакомые дали наводку на LINQ, мол через него можно сделать, но попытки вставить функции в Select или Where не увенчались успехом. На данный момент имею следующий полностью рабочий и уже используемый код:

    Dim rst20 = From fields In db.PARAM_POL_VZL_M _
                      Where fields.BN = BN.Text And fields.DATA_VR_VIL > DateAdd("y", -90, Now()) _
                      Select fields.VR_POL, fields.N2PC, fields.MAX_NAD_GK, fields.KOL_RVPP
    
    
            For Each row In rst20
                If row.VR_POL.HasValue Then m_nalet = m_nalet + Hour2Min(row.VR_POL)
                If row.N2PC.HasValue Then m_land = m_land + row.N2PC
                If row.MAX_NAD_GK.HasValue Then m_nadduv = m_nadduv + IIf(row.MAX_NAD_GK = 0, 0, 1) / 90
                If row.KOL_RVPP.HasValue Then m_rvpp = m_rvpp + row.KOL_RVPP
            Next
            m_nalet = m_nalet / 90
            m_land = m_land / 90
            m_nadduv = m_nadduv / 90
            m_rvpp = m_rvpp / 90
    Но все равно, буду признателен, если кто хотя бы в LINQ расскажет как вставлять функции\использовать оператор, а то угнетает ,что в Access это занимает 2 строки запроса, а в ASP.NET добавляет к запросу 10 дополнительных строк.

    11 апреля 2012 г. 12:30
  • "Без указания требуемых к выполнению в запросе функций - все работает, но эти функции надо выполнять. Брать отдельно из базы данных нужные поля и отдельно обрабатывать - получится не так красиво, как хотелось бы, да и еще большая нагрузка на сервер." - Вы думаете что если Access встраивает вызовы в функции непосредственно в запрос, а в .Net этого нельзя делать то запросы в ASP.NET становятся неэффективными? Как раз таки нет. Вызовы функций происходит "за кулисами", просто сокращается набор вводимого кода, а насколько это оптимально и эффективно ещё очень большой вопрос?

    "Брать отдельно из базы данных нужные поля и отдельно обрабатывать - получится не так красиво, как хотелось бы, да и еще большая нагрузка на сервер."  - ну не красиво это ещё не значит хорошо, если данные берутся за раз и сохраняются в .net объект(одно поключение и один запрос к базе), одной порцией, и обрабатывает их уже .net функция, то ни о какой дополнительной нагрузке на сервер и речи нет. Это вполне нормальный и оптимальный способ.

    "Но все равно, буду признателен, если кто хотя бы в LINQ расскажет как вставлять функции\использовать оператор, а то угнетает ,что в Access это занимает 2 строки запроса, а в ASP.NET добавляет к запросу 10 дополнительных строк." - использовать альтернативный способ написания выражения linq (синтаксис основанный на вызовах методов(metod based linq sintax in vb.net)) примерно так

    Dim rst20 = db.PARAM_POL_VZL_M _.Where((Function(c) c.BN = BN.Text And c.DATA_VR_VIL > DateAdd("y", -90, Now())

    просто в синтаксисе VB я не очень, но общая идея такая. Тогда свободно можете встраивать вызовы ваших методов, ведь синтаксис linq за кулисами это вызовы методов. Привыкнуть к такому синтаксису не легко но с временем дело поправимое.

    P.S. И мой Вам совет не гонитесь за краткостью, краткость - не всегда хорошо!

    11 апреля 2012 г. 13:51
    Модератор