选择单行时,firstOrDefault()和select()之间有什么区别

时间:2013-09-03 07:31:14

标签: c# asp.net-mvc-3 linq lambda

我是Linq的新手。

我喜欢这个简单的lambda表达式:

crmContext.CallForTags.FirstOrDefault(x => x.CallForText.Contains(callAgainForText)).RowID;

它会在一行中返回我想要的内容。

但是有类似的linq表达式:

crmContext.CallForTags.Where(x => x.CallForText.Contains(callAgainForText)).Select(x => x.RowID);

我希望这会做同样的事情并返回给我RowID

但它确实给我错误说:

无法将IQueryable隐式转换为int

我试着在网上搜索。但是找不到类似的帖子??

任何人都可以帮助我理解,它有何不同? 两个之间是否有任何性能开销? 关于绩效,哪一种方法更好?

6 个答案:

答案 0 :(得分:2)

Select会返回IEnumerable<T>。如果只有一个元素,它将返回带有一个元素的IEnumerable<T>

http://msdn.microsoft.com/en-us/library/system.linq.enumerable.select.aspx

FirstOrDefault返回T的单个实例。

http://msdn.microsoft.com/en-us/library/system.linq.enumerable.firstordefault.aspx

使用您的第一个查询,您说“给我CallForText包含值callAgainForText的第一行的RowID(如果不存在,则为类型的默认值)。”

使用第二个查询,您实际上是在说“为CallForText包含callAgainForText的值的每一行提供RowID”。这将始终返回IEnumerable,即使它只包含一个项目。

然后,您尝试将此查询的结果(返回多个项目)分配给单个T实例,这当然不起作用。

答案 1 :(得分:1)

这部分将为您提供完整的一行

//some IQueryable  = crmContext.CallForTags.Where(x => x.CallForText.Contains(callAgainForText));

现在因为你使用select来获得单列的值然后尝试将它带入一个像上面的int变量,因为它返回一个IEnumerable

Int32 test = crmContext.CallForTags.Where(x => x.CallForText.Contains(callAgainForText)).RowID;

当您使用where然后column name时,它会提供一个值,或FirstorDefault()代表完整的行。

FirstOrDefault返回与条件匹配的第一个元素,或者为null。

答案 2 :(得分:0)

当你使用select时,返回你在lambda表达式中指定的元素的IEnumerable,SingleOrDefault或FirstorDefault将返回实际类型而不是它的可枚举类型。

答案 3 :(得分:0)

在第一个表达式中,如果有任何结果并且访问其RowID属性(可能NullReferenceException那里),则要求仅返回一个结果,我假设它是int类型。

在第二个表达式中,您要求根据条件过滤列表,然后要求检索结果中每个项目的RowID属性。我假设您要将其分配给int类型的变量,这需要从IQueryableint的隐式转换,因此是错误。

答案 4 :(得分:0)

假设RowID是一个int,那么:

crmContext.CallForTags.FirstOrDefault(x => x.CallForText.Contains(callAgainForText)).RowID

将返回一个int,即RowID。但是,如果序列为空,FirstOrDefault()将为引用类型返回null,这意味着当您尝试在此情况下取消引用.RowID时,它将抛出NullReferenceException。

crmContext.CallForTags.Where(x => x.CallForText.Contains(callAgainForText)).Select(x => x.RowID);

将返回与谓词RowID匹配的所有项的所有x.CallForText.Contains(callAgainForText)值的序列。

注意这是一个序列,而不是一个int! (按“序列”我的意思是IEnumerable<T>。)

答案 5 :(得分:0)

FirstOrDefault返回与谓词匹配的第一个元素,或者为null(如果未找到匹配项)。返回类型将是int(如果谓词返回true),因为您只选择first元素,或者如果谓词返回false,则返回null

rmContext.CallForTags.Where(x => x.CallForText.Contains(callAgainForText)).Select(x => x.RowID);

Selects包含callAgainForText并返回IEnumerable of integers (Which are the Row ID's) or more specifically IEnumerable<int>

的所有项目