7

私は Linq to Entity を初めて使用します。これが私のテスト シナリオです。

  • ユーザーがいます
  • ユーザーにはフォト アルバムがあります。アルバムは 1 人のユーザーのみに属します
  • アルバムには写真があります。写真は 1 つのアルバムにのみ属します
  • 写真にはタグが付いています。タグは多くの写真に属する場合があります

DB テーブル

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 と同じくらい簡単になりました。まだナビゲーション プロパティはなく、db には関係がありません。

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()
              };
4

2 に答える 2

6

まず最初に、データベースに外部キーを設定してから EF を再構築する必要があります。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();
于 2012-11-06T12:18:38.987 に答える
6

すべての写真にタグが少なくとも 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() 
    }
    );
于 2012-11-06T13:55:50.200 に答える