我对使用EF 5进行查询的“最佳实践”感兴趣。
例如,让我们有2个表:电影和流派有多对多的关系,所以有第三个表GenreMovie,其中MovieId和GenreId为FK。
这意味着一种类型有几部电影,但也有一部电影可以混合使用。
在客户端有2个网格,左边是流派列表,右边是电影列表。
对于选定的类型,电影列表不仅会显示该类型的电影,还会显示所有属于此类型的电影。
此选择可以在2路上完成,具有相同的结果。
int genreId = 1; (选择id = 1的流派)
使用EF关联
var q = db.Movies
.Select(m => new
{
MovieId = m.MovieId,
Title = m.Title,
Selected = m.GenreMovies.Where(gm => gm.GenreId == genreId).Count() > 0,
});
使用Linq join
var q = from m in db.Movies
join gm in db.GenreMovies.Where(gm => gm.GenreId == genreId) on m.MovieId equals gm.MovieId into gms
from gm in gms.DefaultIfEmpty()
select new
{
MovieId = m.MovieId,
Title = m.Title,
Selected = gm != null
};
显然,第一种方法代码更少,看起来更简单。
但它是真的更好的方式,也是最好的做法?
因为我听说EF关联并不总能最好地转换为有关优化的SQL查询。
我还研究了Sql Profiler以查看两种方式的结果查询。 我看到以下内容:(1。方式似乎用更多的行进行查询,但我不确定它是否效率较低)???
我尝试用几十万条记录进行一些测试,但两种方式都太快,看不出任何差异。
1
exec sp_executesql N'SELECT
[Project2].[MovieId] AS [MovieId],
[Project2].[Title] AS [Title],
CASE WHEN ([Project2].[C1] > 0) THEN cast(1 as bit) WHEN ( NOT ([Project2].[C2] > 0)) THEN cast(0 as bit) END AS [C1]
FROM ( SELECT
[Project1].[MovieId] AS [MovieId],
[Project1].[Title] AS [Title],
[Project1].[C1] AS [C1],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[GenreMovie] AS [Extent3]
WHERE ([Project1].[MovieId] = [Extent3].[MovieId]) AND ([Extent3].[GenreId] = @p__linq__0)) AS [C2]
FROM ( SELECT TOP (1000)
[c].[MovieId] AS [MovieId],
[c].[Title] AS [Title],
(SELECT
COUNT(1) AS [A1]
FROM [dbo].[GenreMovie] AS [Extent2]
WHERE ([c].[MovieId] = [Extent2].[MovieId]) AND ([Extent2].[GenreId] = @p__linq__0)) AS [C1]
FROM [dbo].[Movie] AS [c]
) AS [Project1])
AS [Project2]',N'@p__linq__0 int',@p__linq__0=1
2
exec sp_executesql N'SELECT
[Limit1].[MovieId] AS [MovieId],
[Limit1].[Title] AS [Title],
CASE WHEN ([Limit1].[GenreMovieId] IS NOT NULL) THEN cast(1 as bit) WHEN ([Limit1].[GenreMovieId] IS NULL) THEN cast(0 as bit) END AS [C1]
FROM ( SELECT TOP (1000)
[Extent1].[MovieId] AS [MovieId],
[Extent1].[Title] AS [Title],
[Extent2].[GenreMovieId] AS [GenreMovieId]
FROM [dbo].[Movie] AS [Extent1]
LEFT OUTER JOIN [dbo].[GenreMovie] AS [Extent2] ON ([Extent2].[GenreId] = @p__linq__0) AND ([Extent1].[MovieId] = [Extent2].[MovieId]))
AS [Limit1]',N'@p__linq__0 int',@p__linq__0=1
答案 0 :(得分:0)
我会这样写:
var q = db.Movies
.Select(m => new
{
MovieId = m.MovieId,
Title = m.Title,
Selected = m.GenreMovies.Any(gm => gm.GenreId == genreId),
});
仅出于简单原因。