【问题标题】:Linq to Entity Join and Group ByLinq to Entity Join 和 Group By
【发布时间】:2012-10-26 09:03:33
【问题描述】:

我是 Linq to Entity 的新手,这是我的测试场景:

  • 有用户
  • 用户有相册。一张专辑只属于一个用户
  • 相册有照片。一张照片只属于一个相册
  • 照片有标签。一个标签可能属于多张照片

我想编写一个方法,使用 Linq 显示在特定用户的相册中使用的标签的计数和名称。

这是我写的方法,效果很好

    public static void TestStatistics(int userId)
    {
        // select AlbumTitle, TagName, TagCount where UserId = userId
        var results = from photo in dbSet.PhotoSet
                      join album in dbSet.AlbumSet on photo.AlbumId equals album.Id into albumSet
                      from alb in albumSet
                      where alb.UserId == userId
                      join photoTag in dbSet.PhotoTagSet on photo.Id equals photoTag.PhotoId into photoTagSet
                      from pt in photoTagSet
                      join tag in dbSet.TagSet on pt.TagId equals tag.Id
                      group new { alb, tag } by new { alb.Title, tag.Name }
                          into resultSet
                          orderby resultSet.Key.Name
                          select new
                          {
                              AlbumTitle = resultSet.Key.Title,
                              TagName = resultSet.Key.Name,
                              TagCount = resultSet.Count()
                          };

        foreach (var item in results)
        {
            Console.WriteLine(item.AlbumTitle + "\t" + item.TagName + "\t" + item.TagCount);
        }
    }

这是执行相同操作的标准 T-SQL 查询

SELECT  a.Title AS AlbumTitle, t.Name AS TagName , COUNT(t.Name) AS TagCount
FROM    TblPhoto p, TblAlbum a, TblTag t, TblPhotoTag pt
WHERE   p.Id = pt.PhotoId AND t.Id = pt.TagId AND p.AlbumId = a.Id AND a.UserId = 1
GROUP BY a.Title, t.Name 
ORDER BY t.Name

很明显,标准的 T-SQL 查询比 Linq 查询简单得多。 我知道 Linq 不应该比 T-SQL 更简单,但是这种复杂性差异让我觉得我做错了什么。此外,Linq 生成的 SQL 查询极其复杂。

有什么方法可以让 Linq 查询更简单?

更新 1:

我没有使用连接,而是使用 T-SQL 中使用的方法使其变得更简单。实际上它现在就像 T-SQL 一样简单。数据库上仍然没有导航属性和关系。

var results = from photo in dbSet.PhotoSet
              from album in dbSet.AlbumSet
              from photoTag in dbSet.PhotoTagSet
              from tag in dbSet.TagSet
              where photo.AlbumId == album.Id && photo.Id == photoTag.PhotoId &&
                    tag.Id == photoTag.TagId && album.UserId == userId
              group new { album, tag } by new { album.Title, tag.Name } into resultSet
              orderby resultSet.Key.Name
              select new {
                  AlbumTitle = resultSet.Key.Title,
                  TagName = resultSet.Key.Name,
                  TagCount = resultSet.Count()
              };

【问题讨论】:

    标签: c# linq tsql linq-to-entities


    【解决方案1】:

    如果每张照片至少有一个标签,那么试试

    var results = (from r in PhotoTag 
        where r.Photo.Album.UserID == userId
        group r by new { r.Photo.Album.Title, r.Tag.Name } into resultsSet
        orderby resultsSet.Key.Name 
        select new 
        { 
            AlbumTitle = resultsSet.Key.Title , 
            TagName    = resultsSet.Key.Name , 
            TagCount   = resultsSet.Count() 
        }
        );
    

    【讨论】:

    • 谢谢,这几乎是我所期望的。似乎我尝试了错误的入口点,PhotoTag 是正确的入口点。顺便说一句,这需要在 db 和导航属性中定义关系。
    【解决方案2】:

    首先,您需要在数据库中设置外键,然后重建 EF,它将“知道”(即导航属性)关系,然后允许您省略所有联接并使用类似的东西以下:

    List<AlbumTag> query = (from ps in dbSet.PhotoSet
                             where ps.Album.UserId = userId
                             group new { album, tag } by new { ps.Album.Title, ps.PhotoTag.Tag.Name } into resultSet
                             orderby resultSet.Key.Name
                             select new AlbumTag()
                             {
                               AlbumTitle = resultSet.Key.Title,
                               TagName = resultSet.Key.Name,
                               TagCount = resultSet.Count()
                             }).ToList();
    

    【讨论】:

    • 感谢您的回答。我明白你的意思,但ps.PhotoTag 是集合,所以在那之后我不能使用.Tag。如果我使用FirstOrDefault 代码执行但给出错误结果
    猜你喜欢
    • 2023-04-08
    • 1970-01-01
    • 1970-01-01
    • 2011-05-18
    • 2023-03-31
    • 1970-01-01
    • 1970-01-01
    • 2010-09-23
    • 2021-11-06
    相关资源
    最近更新 更多