2010-04-20 123 views
2

我阅读了关于在Linq-To-Entity上使用SingleOfDefault的类似问题的其他文章,有人建议使用“First()”和其他一些建议使用“Extension”方法来实现单()。Linq to Entities不支持方法'SingleOrDefault'

此代码抛出异常:

Movie movie = (from a in movies 
       where a.MovieID == '12345' 
        select a).SingleOrDefault(); 

如果我使用.ToList(转换对象查询到List)“的SingleOrDefault()”实际工作完全不抛出任何错误。

我的问题是:转换为List不好吗?对于更复杂的查询会是性能问题吗?它在SQL中被翻译成什么?

Movie movie = (from a in movies.ToList() 
       where a.MovieID == '12345' 
        select a).SingleOrDefault(); 
+1

你使用的是3.5吗?因为4.0中支持SingleorDefualt – Nix 2010-04-20 16:06:51

回答

5

就linq 2实体团队而言,它在提供程序级别上不受支持,但有多种方法可以检查here

但据我所知,它现在在.NET 4中支持。

1

LinqToEntities(4)支持SingleOrDefault。

我的假设是你使用EF 3.5?

有没有简单的方法来做1或null。

我会写一个使用count的exention,它可以很好地扩展。

public static TElement SingleOrDefault<TElement> 
    (this IQueryable<TElement> query) 
{ 
    if (query.Count() > 1) 
    { 
     throw new Exception(); 
    } 
    return query.FirstOrDefault(); 
} 
+0

当您指'.Any()'时,不要使用'.Count()> 1'。 '.Any()'映射到SQL中的'EXISTS',远比* COUNT'更有效。使用'.Any()';也更具有表现力。你告诉提供者,“以最有效的方式做到这一点”,而不是“使用此算法来查看是否存在”。 – 2010-04-20 16:39:42

+1

呃,我的意思是'.Count> 0',当然这不是你写的。*然而,'.Count> 1'仍然不是取代'.Single()'的正确方法。在底层,EF 4更像'.Take(2).AsEnumerable()。Count()',这更接近你想要的东西。同样,这个想法是避免运行一个完全独立的查询,它在数据库服务器上计算出一个实际上并不需要的大数字。无论如何,对于我误解你上面的答案表示歉意。 – 2010-04-20 17:55:21

3

一般来说,不好叫.ToList()或.AsEnumerable(),因为它会强制评估查询,并从SQL获取的所有数据。

在您的示例中,.ToList()处于特别糟糕的位置,因为它将获取所有电影。先去哪里,然后去ToList会更好。

最短的要在EF何种形式之前EF4是: -

var movie = movies.FirstOrDefault(a => a.MovieID = 12345); 

通过使在数据库强制执行单MovieID主键似乎是一个更好的方式,以确保有永远只一个具有任何给定ID的电影。

相关问题