2

音乐家写歌。歌曲在空中播放。

我有数据库表 Musicians、Songs 和 AirTimes。AirTimes 表条目包含有关在哪个日期播放了哪首歌以及播放了多少分钟的信息。

我有与表格相对应的音乐家、歌曲、通话时间等课程。这些类具有指向另一个实体的导航属性。下面的箭头代表导航。

音乐家 <--> 歌曲 <--> 通话时间

从数据库中,我必须检索他/她的歌曲获得 AirTime 的所有音乐家和日期。另外,我想显示特定日期播放的歌曲数量以及该日期播放的分钟数。

在 Microsoft SQL 中,我会这样做:

select 
    dbo.Musicians.LastName
  , dbo.AirTimes.PlayDate
  , count(dbo.AirTimes.PlayDate) as 'No. of entries'
  , sum(dbo.AirTimes.Duration) as 'No. of minutes'
from dbo.Musicians
  left outer join dbo.Songs
  on dbo.Musicinas.MusicianId = dbo.Songs.MusicianId
    left outer join dbo.AirTimes
    on dbo.Songs.SongId = dbo.AirTimes.SongId
    and '2014-07-01T00:00:00' <= dbo.AirTimes.PlayDate 
    and dbo.AirTimes.PlayDate <= '2014-07-31T00:00:00'
group by 
    dbo.Musicians.LastName
  , dbo.AirTimes.PlayDate
order by
    dbo.Musicians.LastName
  , dbo.AirTimes.PlayDate

任何人都可以将其“翻译”成 linq-to-entitese 吗?

2012 年 8 月 9 日更新
我无法确认 grudolf 的计划是否符合我的要求。我用不同的技术完成了一些事情。尽管如此,我接受他/她的回答。

4

1 回答 1

2

由于您在两个方向都有导航属性,因此您可以从 AirTimes 开始:

var grpTime = (
    from a in AirTimes
    where a.Date >= firstDate && a.Date < lastDate
    group a by new {a.Song.Musician.LastName, a.Song.Title, a.Date} into grp
    select new {
        grp.Key.LastName,
        grp.Key.Title,
        grp.Key.Date,
        Plays = grp.Count(),
        Seconds = grp.Sum(x => x.Duration)
    }
);

或来自音乐家:

var grpMus = (
    from m in Musicians
    from s in m.Songs
    from p in s.Plays
    where p.Date >= firstDate && p.Date < lastDate
    group p by new {m.LastName, s.Title, p.Date} into grp
    select new {
        grp.Key.LastName,
        grp.Key.Title,
        grp.Key.Date,
        Plays = grp.Count(),
        Seconds= grp.Sum(x => x.Duration)
    }
);

编辑:要显示所有音乐家,包括那些没有通话时间的音乐家,您可以使用另一个级别的分组 - 在第一步中,您计算​​每首歌曲+天的总数,然后将它们与歌曲的作者分组。它可能可以直接与数据库一起使用,但我没有设法找到一种有效的方法来做到这一点。然而。;) 使用代码,原始的 AirTimes 结果被更改为返回 Musician 而不是他的姓氏,然后加入到所有音乐家的列表中:

//Airtimes for musicians
var grpAir = (
    from a in AirTimes
    where a.Date >= firstDate && a.Date < lastDate
    group a by new {a.Song.Musician, a.Date} into grp
    select new {
        //Musician instead of his LastName for joining. Id would work too
        grp.Key.Musician,
        //grp.Key.Musician.LastName,
        Date=grp.Key.Date,
        Plays = grp.Count(),
        Secs = grp.Sum(x => x.Duration)
    }
);

var res = (
    from m in Musicians
    join g in grpAir on m equals g.Musician into g2
    from g in g2.DefaultIfEmpty()
    orderby m.LastName
    select new {
        m.LastName,
        Date = (g==null ? null : g.Date),
        Plays = (g==null ? 0 : g.Plays),
        Secs = (g==null ? 0 : g.Secs)
    }
);

您可以在https://gist.github.com/3236238找到更完整的 LINQPad 示例

于 2012-08-02T11:00:26.040 回答