C# Linq到实体联接和分组依据
我是Linq to Entity的新手,下面是我的测试场景:C# Linq到实体联接和分组依据,c#,linq,tsql,linq-to-entities,C#,Linq,Tsql,Linq To Entities,我是Linq to Entity的新手,下面是我的测试场景: 有用户 用户有相册。相册只属于一个用户 相册里有照片。一张照片只属于一个相册 照片有标签。标签可能属于许多照片 我想写一个方法来显示使用Linq的特定用户的相册中使用的标记的计数和名称 这是我写的方法,效果很好 public static void TestStatistics(int userId) { // select AlbumTitle, TagName, TagCount where
- 有用户
- 用户有相册。相册只属于一个用户
- 相册里有照片。一张照片只属于一个相册
- 照片有标签。标签可能属于许多照片
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()
};
首先,您需要在数据库中设置foreignkeys,然后重建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();
List query=(来自dbSet.PhotoSet中的ps
其中ps.Album.UserId=UserId
按新的{ps.album.Title,ps.PhotoTag.tag.Name}将新的{album,tag}分组到结果集中
orderby resultSet.Key.Name
选择new AlbumTag()
{
AlbumTitle=resultSet.Key.Title,
标记名=resultSet.Key.Name,
TagCount=resultSet.Count()
}).ToList();
如果每张照片至少有一个标签,请尝试
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()
}
);
谢谢你的回答。我明白你的意思,但是
ps.PhotoTag
是集合,所以我不能在那之后使用.Tag
。如果我使用FirstOrDefault
代码执行,但给出了错误的结果,这正是我所期望的。看来我尝试的切入点是错误的,PhotoTag是正确的切入点。顺便说一句,这需要在db和导航属性中定义关系。