【问题标题】:LINQ select from join table where the same foreign key has records for two different IDsLINQ 从连接表中选择相同的外键具有两个不同 ID 的记录
【发布时间】:2019-10-27 15:58:50
【问题描述】:

好吧,我猜标题有点混乱。基本上我有这 3 张桌子:

Line

id | Name
---------
1  | "A-B"
2  | "A-D"


Stop

id | Name
---------
1  | A
2  | B
3  | C
4  | D

LineStop

Id | LineId | StopId | Order
----------------------------
1  | 1      | 1      | 0
2  | 1      | 2      | 1
3  | 2      | 1      | 0
4  | 2      | 2      | 1
5  | 2      | 3      | 3
4  | 2      | 4      | 4

所以这是某种公共汽车票务系统,我致力于个人改进。

作为输入,我得到出发 StopId (Stop.Id) 和到达 StopId (Stop.Id)。我想选择在他们的路线中有这两个站点的所有线路(这意味着在 LineSop 表中对于同一个 LineId 我将有出发站和到达站的记录,最终我还想考虑Order 列说明公共汽车通过这些站点的顺序,因为即使该线路有两个我感兴趣的站点,如果它们的顺序相反,我仍然不感兴趣。

我知道展示我迄今为止所做的工作是非常可取的,但我在 where 条件下苦苦挣扎,这似乎是这里的关键因素。出于某种原因,我决定加入LineLineStop

var lines = _context.Lines.Join(
            _context.LineStop,
            line => line.Id,
            lineStop => lineStop.LineId,
            (line, lineStop) => lineStop)

但是然后.. 我需要检查相同的LineId 我在LineStop 表中是否有记录,开始和结束StopId,最终当我找到这样的记录时,开始StopId 订购我少比结束StopId订单。

【问题讨论】:

  • 如何先将LineStopsLines 连接起来,然后将结果与Stops 连接起来,例如:_context.LineStop.Join(_context.Lines,ls=>ls.LineId,line => line.Where(w=>w.Id = LineId),(ls,line)=>new {Id = ls.Id,LineId=line.LineId,LineName=line.Name,StopId=ls.StopId,Order=ls.Order}).Join(_context.Stops,lsl=>lsl.StopId,st=>st.Where(w=>w.Id==lsl.StopId),(lsl,st)=>new{lsl.Id,LineId=lsl.LineId,LineName=lsl.Name,StopId=st.Id,StopName=st.Name,Order=lsl.Order}).ToList() 现在使用列表,您可以输入Where(w=>w.StopId == <Id1> || w.StopId == <Id2>) 并获得结果。
  • @vikscool 这个line => line.Where(w => w.Id = LineId) 似乎不正确Line does not contains definition for Where 这似乎是合理的,因为它不是IEnumerable。也许还有办法实现这个逻辑,但不确定。
  • 是的,你是对的,这是一个错误,这里是更新查询 _context.LineStop.Join(_context.Lines,ls=>ls.LineId,line => line.Id,(ls,line)=>new {Id = ls.Id,LineId=line.LineId,LineName=line.Name,StopId=ls.StopId,Order=ls.Order}).Join(_context.Stops,lsl=>lsl.StopId,st=>stId,(lsl,st)=>new{lsl.Id,LineId=lsl.LineId,LineName=lsl.Name,StopId=st.Id,StopName=st.Name,Order=lsl.Order}).ToList() 没有 Where 子句。
  • @vikscool 嗯,这不是很接近预期的结果。我得到了数据,但是在 stopId 和 Order 上都没有过滤(这当然是奖励)。我可以在内存中进行过滤,但这是不可取的。
  • 对不起,因为我不清楚查询,ToList() 只是为了显示结果你总是可以把上面的语句放到一个变量中让我们说var query = <the above statement(without ToList())> 然后你可以做像query.Where(w=>w.StopId ==<id1> || w.stopId==<id2>).OrderBy(ob=>ob.stopId) 一样过滤和排序,然后您可以在其中添加Select() 子句,也可以在Order by 条件之后简单地执行ToList()

标签: c# entity-framework linq-to-entities


【解决方案1】:

希望对你有帮助:

首先我从旅行者那里得到行程:“我想从 Stop: 2 到 Stop:4”。 一旦我知道有两个停靠点的线路,我就会建立停靠点及其顺序。

var lines = new List<Line>() 
{ 
    new Line() { Id = 1, Name = "A-B" },
    new Line() { Id = 2, Name = "A-D" }
}; 

var stops = new List<Stop>() {
    new Stop() { Id = 1, Name = "A" },
    new Stop() { Id = 2, Name = "B" },
    new Stop() { Id = 3, Name = "C" },
    new Stop() { Id = 4, Name = "D" }
};

var lineStops = new List<LineStop>() 
{
    new LineStop() { Id = 1, LineId = 1, StopId = 1, Order = 0 },
    new LineStop() { Id = 2, LineId = 1, StopId = 2, Order = 1 },
    new LineStop() { Id = 3, LineId = 2, StopId = 1, Order = 0 },
    new LineStop() { Id = 4, LineId = 2, StopId = 2, Order = 1 },
    new LineStop() { Id = 5, LineId = 2, StopId = 3, Order = 3 },
    new LineStop() { Id = 4, LineId = 2, StopId = 4, Order = 4 },
};  

var result =  (from trip in (from l  in lines
              join d in lineStops on l.Id equals d.LineId
              join a in lineStops on l.Id equals a.LineId
              where d.StopId == 2 && a.StopId == 4
              select new { d.LineId })
              join l in lines on trip.LineId equals l.Id
              join ls in lineStops on l.Id equals ls.LineId
              select new { l.Name, ls.StopId, ls.Order }).OrderBy(x => x.Order);

预期结果

Name StopId Order
A-D       1    0
A-D       2    1
A-D       3    3
A-D       4    4

【讨论】:

  • 谢谢。我尝试在使用 Linq2Entities 时保持一致,但当我回到我的电脑时会尝试你的建议。
猜你喜欢
  • 1970-01-01
  • 2020-11-26
  • 1970-01-01
  • 2023-03-24
  • 1970-01-01
  • 2013-05-29
  • 2019-03-22
  • 2022-10-05
  • 1970-01-01
相关资源
最近更新 更多