用LINQ模拟SQL外部应用

i5desfxk  于 12个月前  发布在  其他
关注(0)|答案(1)|浏览(129)

我在将下面的存储过程翻译成LINQ时遇到了一些麻烦。

SELECT DISTINCT a0.[recid] AS 'Id'
    ,a0.[latitude] AS 'Latitude'
    ,a0.[longitude] AS 'Longitude'
    ,a0.[countryregionid] AS 'CountryCode'
    ,a0.[level_] as 'Level'
    ,case 
        when wht.[disinfection] is null
        then 0
        else wht.[disinfection]
    end as 'Disinfection'

    ,case when wd1.[fromtime] is null then '' else CONVERT(varchar, DATEADD(ms, wd1.[fromtime] * 1000, 0), 108) end as 'MondayOpen'
    ,case when wd1.[totime] is null then '' else CONVERT(varchar, DATEADD(ms, wd1.[totime] * 1000, 0), 108) end as 'MondayClose'

    ,case when wd2.[fromtime] is null then '' else CONVERT(varchar, DATEADD(ms, wd2.[fromtime] * 1000, 0), 108) end as 'TuesdayOpen'
    ,case when wd2.[totime] is null then '' else CONVERT(varchar, DATEADD(ms, wd2.[totime] * 1000, 0), 108) end as 'TuesdayClose'

    ,case when wd3.[fromtime] is null then '' else CONVERT(varchar, DATEADD(ms, wd3.[fromtime] * 1000, 0), 108) end as 'WednesdayOpen'
    ,case when wd3.[totime] is null then '' else CONVERT(varchar, DATEADD(ms, wd3.[totime] * 1000, 0), 108) end as 'WednesdayClose'

    ,case when wd4.[fromtime] is null then '' else CONVERT(varchar, DATEADD(ms, wd4.[fromtime] * 1000, 0), 108) end as 'ThursdayOpen'
    ,case when wd4.[totime] is null then '' else CONVERT(varchar, DATEADD(ms, wd4.[totime] * 1000, 0), 108) end as 'ThursdayClose'

    ,case when wd5.[fromtime] is null then '' else CONVERT(varchar, DATEADD(ms, wd5.[fromtime] * 1000, 0), 108) end as 'FridayOpen'
    ,case when wd5.[totime] is null then '' else CONVERT(varchar, DATEADD(ms, wd5.[totime] * 1000, 0), 108) end as 'FridayClose'

    ,case when wd6.[fromtime] is null then '' else CONVERT(varchar, DATEADD(ms, wd6.[fromtime] * 1000, 0), 108) end as 'SaturdayOpen'
    ,case when wd6.[totime] is null then '' else CONVERT(varchar, DATEADD(ms, wd6.[totime] * 1000, 0), 108) end as 'SaturdayClose'

    ,case when wd7.[fromtime] is null then '' else CONVERT(varchar, DATEADD(ms, wd7.[fromtime] * 1000, 0), 108) end as 'SundayOpen'
    ,case when wd7.[totime] is null then '' else CONVERT(varchar, DATEADD(ms, wd7.[totime] * 1000, 0), 108) end as 'SundayClose'
FROM [dbo].[address] AS a0

LEFT JOIN  GIR_WashhouseTable as wht on wht.[recid] = a0.[addrrecid]

OUTER APPLY(
    SELECT TOP 1
        awt0.[fromtime]
    ,   awt0.[totime]
    FROM [GIR_AddressWorkTime] as awt0
    WHERE awt0.[dataareaid] = 'v22'
    AND awt0.[active] = 1
    AND awt0.[weekday] = 1
    AND awt0.[refrecid] = a0.[recid]
) as wd1

OUTER APPLY(
    SELECT TOP 1
        awt0.[fromtime]
    ,   awt0.[totime]
    FROM [GIR_AddressWorkTime] as awt0
    WHERE awt0.[dataareaid] = 'v22'
    AND awt0.[active] = 1
    AND awt0.[weekday] = 2
    AND awt0.[refrecid] = a0.[recid]
) as wd2

OUTER APPLY(
    SELECT TOP 1
        awt0.[fromtime]
    ,   awt0.[totime]
    FROM [GIR_AddressWorkTime] as awt0
    WHERE awt0.[dataareaid] = 'v22'
    AND awt0.[active] = 1
    AND awt0.[weekday] = 3
    AND awt0.[refrecid] = a0.[recid]
) as wd3

OUTER APPLY(
    SELECT TOP 1
        awt0.[fromtime]
    ,   awt0.[totime]
    FROM [GIR_AddressWorkTime] as awt0
    WHERE awt0.[dataareaid] = 'v22'
    AND awt0.[active] = 1
    AND awt0.[weekday] = 4
    AND awt0.[refrecid] = a0.[recid]
) as wd4

OUTER APPLY(
    SELECT TOP 1
        awt0.[fromtime]
    ,   awt0.[totime]
    FROM [GIR_AddressWorkTime] as awt0
    WHERE awt0.[dataareaid] = 'v22'
    AND awt0.[active] = 1
    AND awt0.[weekday] = 5
    AND awt0.[refrecid] = a0.[recid]
) as wd5

OUTER APPLY(
    SELECT TOP 1
        awt0.[fromtime]
    ,   awt0.[totime]
    FROM [GIR_AddressWorkTime] as awt0
    WHERE awt0.[dataareaid] = 'v22'
    AND awt0.[active] = 1
    AND awt0.[weekday] = 6
    AND awt0.[refrecid] = a0.[recid]
) as wd6

OUTER APPLY(
    SELECT TOP 1
        awt0.[fromtime]
    ,   awt0.[totime]
    FROM [GIR_AddressWorkTime] as awt0
    WHERE awt0.[dataareaid] = 'v22'
    AND awt0.[active] = 1
    AND awt0.[weekday] = 7
    AND awt0.[refrecid] = a0.[recid]
) as wd7

WHERE a0.[dataareaid] = 'v22' 
AND a0.[active] = 1
AND a0.[level_] <> 0
AND a0.[type] = 153 
AND a0.[ADDRTABLEID] = 52411
AND a0.[countryregionid] IN 
('AT', 'BE', 'BG', 'HR', 'CZ', 'EE', 'FR', 'DE', 'GR', 'HU', 'IE', 'IT', 'LV', 'LT', 'LU', 'NL', 'PL', 'PT', 'RO', 'SK', 'SI', 'ES', 'LI', 'MC', 'SM', 'CH', 'GB', 'DK') -- AIO-833
order by COUNTRYREGIONID

字符串
所以这里的问题是外部应用。我已经研究了通过LINQ模仿外部应用的方法,并看到let关键字可以帮助你做到这一点。但在我的情况下,它并不有用。所以我试着这样做。

var query = 
    from address in _context.Address
    join washHouse in _context.GirWashhousetable
    on address.Addrrecid equals washHouse.Recid into whtGroup
    from washHouse in whtGroup.DefaultIfEmpty()
    join workTime in _context.GirAddressworktime
    on address.Recid equals workTime.Refrecid into workTimeGroup
    from workTime in workTimeGroup.DefaultIfEmpty()
    where address.Dataareaid == "v22"
        && address.Active == 1
        && address.Level != 0
        && address.Type == 153
        && address.Addrtableid == 52411
        && _countryCodesForWashStations.Contains(address.Countryregionid)
        && workTime.Dataareaid == "v22"
        && workTime.Active == 1
    let mondayWorkTime = workTimeGroup.FirstOrDefault(wt => wt.Weekday == 1)
    // Repeat similar logic for other days...
    select new WashingStationsResult
    {
        Id = address.Recid,
        Latitude = address.Latitude,
        Longitude = address.Longitude,
        CountryCode = address.Countryregionid,
        Level = address.Level,
        Disinfection = washHouse.Disinfection,
        MondayOpen = mondayWorkTime != null ? TimeSpan.FromSeconds(mondayWorkTime.Fromtime).ToString(@"hh\:mm\:ss") : string.Empty,
        MondayClose = mondayWorkTime != null ? TimeSpan.FromSeconds(mondayWorkTime.Totime).ToString(@"hh\:mm\:ss") : string.Empty,
        // Repeat similar logic for other days...
    };


如果只有一个let,它可以工作,但如果我在其他日子重复一些,我也会得到空列表作为响应。我不知道为什么。有人能建议什么是解决这个问题的最佳方法吗?

v1l68za4

v1l68za41#

对于OUTER APPLY,您必须使用不同的技术:集合选择器在非where情况下引用外部

var query = 
    from address in _context.Address
    join washHouse in _context.GirWashhousetable
        on address.Addrrecid equals washHouse.Recid into whtGroup
    from washHouse in whtGroup.DefaultIfEmpty()
    from mondayWorkTime in _context.GirAddressworktime
        .Where(workTime => address.Recid == workTime.Refrecid 
            && workTime.Dataareaid == "v22"
            && workTime.Active == 1
        )
        .Take(1)
        .DefaultIfEmpty()
            
    // Repeat similar logic for other days...

    where address.Dataareaid == "v22"
        && _countryCodesForWashStations.Contains(address.Countryregionid)
        && address.Active == 1
        && address.Level != 0
        && address.Type == 153
        && address.Addrtableid == 52411
    select new WashingStationsResult
    {
        Id = address.Recid,
        Latitude = address.Latitude,
        Longitude = address.Longitude,
        CountryCode = address.Countryregionid,
        Level = address.Level,
        Disinfection = washHouse.Disinfection,
        MondayOpen = mondayWorkTime != null ? TimeSpan.FromSeconds(mondayWorkTime.Fromtime).ToString(@"hh\:mm\:ss") : string.Empty,
        MondayClose = mondayWorkTime != null ? TimeSpan.FromSeconds(mondayWorkTime.Totime).ToString(@"hh\:mm\:ss") : string.Empty,
        // Repeat similar logic for other days...
    };

字符串
为了简化查询,您可以使用预定义的过滤器准备记录:

var workTimes = _context.GirAddressworktime
    .Where(workTime => 
            && workTime.Dataareaid == "v22"
            && workTime.Active == 1
        );

var query = 
    from address in _context.Address
    join washHouse in _context.GirWashhousetable
        on address.Addrrecid equals washHouse.Recid into whtGroup
    from washHouse in whtGroup.DefaultIfEmpty()
    from mondayWorkTime in workTimes
        .Where(workTime => address.Recid == workTime.Refrecid && workTime.WeekDay == 1)
        .Take(1)
        .DefaultIfEmpty()
    // Repeat similar logic for other days...

    where address.Dataareaid == "v22"
        && _countryCodesForWashStations.Contains(address.Countryregionid)
        && address.Active == 1
        && address.Level != 0
        && address.Type == 153
        && address.Addrtableid == 52411
    select new WashingStationsResult
    {
        Id = address.Recid,
        Latitude = address.Latitude,
        Longitude = address.Longitude,
        CountryCode = address.Countryregionid,
        Level = address.Level,
        Disinfection = washHouse.Disinfection,
        MondayOpen = mondayWorkTime != null ? TimeSpan.FromSeconds(mondayWorkTime.Fromtime).ToString(@"hh\:mm\:ss") : string.Empty,
        MondayClose = mondayWorkTime != null ? TimeSpan.FromSeconds(mondayWorkTime.Totime).ToString(@"hh\:mm\:ss") : string.Empty,
        // Repeat similar logic for other days...
    };

相关问题