【问题标题】:Converting SQL to LINQ with Multiple Tables and Group使用多个表和组将 SQL 转换为 LINQ
【发布时间】:2020-04-30 18:00:55
【问题描述】:

似乎有很多关于 SQL to LINQ 的问题,但我似乎找不到连接表和分组的示例;特别是需要从多个表中获取数据。

使用这个简单的 SQL:

SELECT
    s.showId, s.showName, v.venueName, Min(dateTime) startDate
FROM
    shows s
    INNER JOIN venues v ON s.venueId = v.venueId
    INNER JOIN showDates d ON s.showId = d.showId
GROUP BY
    s.showId

我能想到的最好的是以下

var ungrouped = (
    from s in db.Shows
    join v in db.Venues on s.VenueId equals v.VenueId
    join d in db.ShowDates on s.ShowId equals d.ShowId
    select new { s, v, d }
).ToList();

var grouped = (
    from s in ungrouped
    group s by s.s.ShowId into grp
    select new
    {
        showId = grp.Key,
        name = (from g in grp select g.s.showName).FirstOrDefault(),
        venue = (from g in grp select g.v.VenueName).FirstOrDefault(),
        startDate = grp.Max(g => g.d.DateTime)
    }
);

这可行,但感觉很乱。我不喜欢:

  • 它被分成两个语句
  • 不得不反复写(from g in grp select ...).FirstOrDefault()
  • s.s.ShowId这样的位
  • 它的代码行数比 SQL 多得多

这个例子是一个简单的例子,当我有 5+ 个表要加入和 10+ 个列要选择时,它只会变得更糟。

问题:这是最好的方法吗,我应该接受它;还是有更好的方法来编写这个查询?

【问题讨论】:

  • 只是好奇,您想使用 LINQ to SQL 重写它的真正原因是什么?
  • 我正在将 PHP 应用程序转换为 .net MVC。数据库以类表示,我知道 Linq 是要走的路——尽管接受建议!
  • 第一个建议是使用原始的原始sql,尤其是当您将应用程序迁移到不同的平台时,尽量不要更改与平台无关的代码以避免可能的错误。
  • 您要迁移到 .net core 3 吗? Linq GroupBy 的工作方式发生了一些重大变化,您可能需要注意:stackoverflow.com/questions/58138556/…

标签: c# linq


【解决方案1】:

我不确定您是否正在寻找类似的东西,但它更简洁,它没有分成 2 个语句,您可能会发现它很有帮助。我无法使用 dbcontext,所以我使用列表来确保语法正确。

var res = Shows.Join(Venues,
         show => show.VenueID,
         venue => venue.VenueID,
            (show, venue) => new { show, venue })
                .Join(ShowDates,
                    val => val.show.ShowID,
                    showdate => showdate.ShowID,
                        (val, showDate) => new { val.show, val.venue, showDates = showDate })
                            .GroupBy(u => u.show.ShowID)
                            .Select(grp => new
                            {
                                showId = grp.Key,
                                name = grp.FirstOrDefault()?.show.showName,
                                venue = grp.FirstOrDefault()?.venue.VenueName,
                                startDate = grp.Max(g => g.showDates.DateTime)
                            });

【讨论】:

  • 确实解决了第二个语句的问题,但同样混乱:)
【解决方案2】:

我们现在需要在他们之间进行一对一或一对多的联系,但离这个答案不会太远。

 var GrouppedResult = Shows.Include(x=>x.Veneu).Include(x=>x.ShowDates)
    .Where(x=>x.Veneu.Any()&&x.ShowDates.Any())
    .GroupBy(x=>x.ShowId)
    .Select(x=>///anything you want);

from show in Shows
join veneu in Veneu on veneu.VeneuId equals show.VeneuId
join showDates in ShowDates on showDates.ShowId=show.ShowID
group show by show.Id into grouppedShows
select new { ///what you want };

【讨论】:

  • 两者都有一对多(场地可以有很多节目,节目有很多日期)。你的答案不起作用;这些关系没有在任何地方的代码中定义——应该是吗?
  • 使用一个你需要定义虚拟成员。但它是如何不起作用的,你能告诉我更多吗?
猜你喜欢
  • 2021-06-01
  • 1970-01-01
  • 2016-06-17
  • 2012-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-31
  • 2021-09-17
相关资源
最近更新 更多