使用 LINQ 模仿 SQL 外部应用

问题描述 投票:0回答:1

我在将以下存储过程转换为 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,它会起作用,但如果我在其他日子重复一些,我也会得到空列表作为响应。我不知道为什么。有人可以建议什么是解决这个问题的最佳方法吗?

c# .net entity-framework linq
1个回答
0
投票

对于 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 
            && 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
        )
        .Take(1)
        .DefaultIfEmpty()
    // 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...
    };
© www.soinside.com 2019 - 2024. All rights reserved.