【问题标题】:convert SQL to LINQ not working将 SQL 转换为 LINQ 不起作用
【发布时间】:2018-07-04 05:54:12
【问题描述】:

我想将此 SQL 代码转换为 LINQ。这是我的 SQL 代码:

SELECT Rooms.RoomName AS RoomNo, Beds.BedName AS Beds, Rooms.RoomType, ISNULL(CheckIn.CheckIntatus,'') AS Status 
FROM CheckIn
INNER JOIN GuestBeds ON CheckIn.GuestBedId = GuestBeds.Id
AND (CheckIn.CheckInStatus = 1 OR CheckIn.CheckIntatus = 2 OR CheckIn.CheckSIntatus = 3) 
RIGHT JOIN Beds ON GuestBeds.BedId = Beds.Id
INNER JOIN Rooms ON Beds.RoomId = Rooms.Id
LEFT JOIN Guests ON CheckIn.GuestId = Guests.Id
WHERE Beds.Active = 1 AND Rooms.Active = 1
ORDER BY RoomName, Beds

它运行良好,这意味着它显示了所有带有 CheckInStatus 的 RoomName。如果房间在 CheckIn 表中不存在,ot 将返回状态为 Null。 所以我想将代码转换为 LINQ。所以这是我的 LINQ 代码:

from b in Beds 
join w in Rooms on b.RoomsId equals w.Id
where (a.CheckInStatus == 3 || a.CheckInStatus == 1 || a.CheckInStatus == 2)
join p in GuestBeds on b.Id equals p.BedId
join a in CheckIn on p.Id equals a.GuestBedId 
join t in Guests on a.GuestId equals t.Id
where b.Active == true && w.Active == true
orderby w.RoomName
select new
{
    RoomName = w.RoomName,
    BedName = b.BedName,
    Status = a.CheckInStatus
}

它不像第一个代码那样工作。它只显示包含 CheckInStatus 的数据。我希望它显示 Room 数据库中的所有 RoomName

【问题讨论】:

  • 看起来您的 SQL 正在使用 LEFT 和 RIGHT 连接,但您的 LINQ 没有考虑到这一点。看看这是否有帮助:stackoverflow.com/questions/4497086/…
  • 有什么原因你没有复制/粘贴你的 SQL 吗?它有错误...

标签: c# sql linq inner-join right-join


【解决方案1】:

通常我会发布一些将 SQL 转换为 LINQ 的规则,但这已经够复杂了,我认为我需要制定新规则。我注释掉了对Guests 的引用,因为作为LEFT JOIN 它与答案无关。

在单个表上提取WHERE 并使它们成为子查询:

var ActiveBeds = Beds.Where(b => b.Active == 1);
var ActiveRooms = Rooms.Where(r => r.Active == 1);

在 LINQ 中,RIGHT JOIN 必须通过将连接翻转为左连接来完成,因此我们将创建两侧作为子查询。

RIGHT JOIN的左侧:

将不属于 equi-join 的 JOIN 条件转换为相应表上的 LINQ where 子句(或者,这可能是上面的子查询)。 LEFT JOIN 变为 LINQ join/from ... DefaultIfEmpty() 短语,但如上所述,不需要。

var CheckInsGuestBedsGuests = from c in CheckIn
                              where (c.CheckInStatus == 1 || c.CheckInStatus == 2 || c.CheckInStatus == 3)
                              join gb in GuestBeds on c.GuestBedId equals gb.Id
                              //join g in Guests on c.GuestId equals g.Id into gj
                              //from g in gj.DefaultIfEmpty()
                              select new { c, gb /*, g */ };

RIGHT JOIN的右侧:

RIGHT JOIN 的另一边包含一个INNER JOIN,所以将它们放在一个子查询中:

var ActiveBedsRooms = from b in ActiveBeds
                      join r in ActiveRooms on b.RoomId equals r.Id
                      select new { b, r };

最后,翻转子查询以使用与上述相同的习语创建左连接:

var ans = from br in ActiveBedsRooms
          join cgbg in CheckInsGuestBedsGuests on br.b.Id equals cgbg.gb.BedId into cgbgj
          from cgbg in cgbgj.DefaultIfEmpty()
          select new {
              RoomNo = br.r.RoomName,
              Beds = br.b.BedName,
              br.r.RoomType,
              Status = cgbg.c.CheckInStatus
          };

注意:如果您没有使用 LINQ to SQL,当 cgbgnull 时,Status 表达式将失败,您需要

              Status = cgbg?.c.CheckInStatus

但不幸的是,LINQ to SQL/EF 还没有处理空条件运算符。

顺便说一句,很好的查询 - 让我想起了我以前写酒店前台软件的时候:)

【讨论】:

    猜你喜欢
    • 2019-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多