私は Linq to Entity を初めて使用します。これが私のテスト シナリオです。
- ユーザーがいます
- ユーザーにはフォト アルバムがあります。アルバムは 1 人のユーザーのみに属します
- アルバムには写真があります。写真は 1 つのアルバムにのみ属します
- 写真にはタグが付いています。タグは多くの写真に属する場合があります
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()
};