Asp.net mvc 4 检索单个字段值时的FirstOrDefault()
这类事情一直困扰着我,所以我想我应该从你们这些聪明人那里寻找一个“更好的方法” 我有一个查询,我想返回单个字段的值,它是一个int值Asp.net mvc 4 检索单个字段值时的FirstOrDefault(),asp.net-mvc-4,entity-framework-4,dbcontext,Asp.net Mvc 4,Entity Framework 4,Dbcontext,这类事情一直困扰着我,所以我想我应该从你们这些聪明人那里寻找一个“更好的方法” 我有一个查询,我想返回单个字段的值,它是一个int值 int thivalue = (from q in context.tablename where q.ID == id orderby q.fieldname descending select q).FirstOrDefault().fieldname; 问题是查询可能不会返回任何结果,在这种情况下,我希望该值为0 当然,如果
int thivalue = (from q in context.tablename
where q.ID == id
orderby q.fieldname descending
select q).FirstOrDefault().fieldname;
问题是查询可能不会返回任何结果,在这种情况下,我希望该值为0
当然,如果没有结果,我会在尝试访问不存在的字段时遇到异常。看来我的选择是
a) 返回行(我不需要),这样我就可以测试null并从那里开始,或者
b) 用try-catch将其包裹起来,然后将值设置为0,这看起来有点笨重
我想DefaultIfEmpty()可能会对我有所帮助,但如果我想要的只是一个值,那么它似乎就没有帮助了
那么正确的方法是什么呢?我只是固执地不想返回整行,而只需要其中的一个值吗
附录:(如果有人感兴趣)
在他的回答中,伯克利·罗斯给了我两个明显相同的选择。但是只有第二个给了我正确的结果。OrderByDesting似乎有点不对劲。我用“一瞥”查看了每个问题的查询
var nextSequence = db.PaneContents
.Where(q=>q.QuizPaneID == quizPaneId)
.OrderByDescending(q=>q.Sequence)
.Select (q=>q.Sequence)
.DefaultIfEmpty()
.First();
已生成此查询:
SELECT
CASE WHEN ([Limit1].[C1] IS NULL) THEN 0 ELSE [Limit1].[Sequence] END AS [C1]
FROM ( SELECT TOP (1)
[Project1].[Sequence] AS [Sequence],
[Project1].[C1] AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
LEFT OUTER JOIN (SELECT
[Extent1].[Sequence] AS [Sequence],
cast(1 as tinyint) AS [C1]
FROM [dbo].[PaneContents] AS [Extent1]
WHERE [Extent1].[QuizPaneID] = 274 /* @p__linq__0 */ ) AS [Project1] ON 1 = 1
) AS [Limit1]
SELECT TOP (1)
[Project1].[Sequence] AS [Sequence]
FROM ( SELECT
[Extent1].[Sequence] AS [Sequence]
FROM [dbo].[PaneContents] AS [Extent1]
WHERE [Extent1].[QuizPaneID] = 274 /* @p__linq__0 */
) AS [Project1]
ORDER BY [Project1].[Sequence] DESC
鉴于
var nextSequence = (from q in db.PaneContents
where q.QuizPaneID == quizPaneId
orderby q.Sequence descending
select q.Sequence).FirstOrDefault();
已生成此查询:
SELECT
CASE WHEN ([Limit1].[C1] IS NULL) THEN 0 ELSE [Limit1].[Sequence] END AS [C1]
FROM ( SELECT TOP (1)
[Project1].[Sequence] AS [Sequence],
[Project1].[C1] AS [C1]
FROM ( SELECT 1 AS X ) AS [SingleRowTable1]
LEFT OUTER JOIN (SELECT
[Extent1].[Sequence] AS [Sequence],
cast(1 as tinyint) AS [C1]
FROM [dbo].[PaneContents] AS [Extent1]
WHERE [Extent1].[QuizPaneID] = 274 /* @p__linq__0 */ ) AS [Project1] ON 1 = 1
) AS [Limit1]
SELECT TOP (1)
[Project1].[Sequence] AS [Sequence]
FROM ( SELECT
[Extent1].[Sequence] AS [Sequence]
FROM [dbo].[PaneContents] AS [Extent1]
WHERE [Extent1].[QuizPaneID] = 274 /* @p__linq__0 */
) AS [Project1]
ORDER BY [Project1].[Sequence] DESC
看起来在第一个示例中,OrderByDescending()不知为何在翻译过程中丢失了?
无论如何,出于我的目的,不需要DefaultIfEmpty(),第二个示例更简单。我只是觉得奇怪,它不起作用(我说的“不起作用”是指它选择了错误的值,因为它没有按降序排序),因为它看起来应该这样做 我会这样做
int thisvalue = context.tablename
.Where(q => q.ID == id)
.OrderByDescending(q => q.fieldname)
.ToList()
.DefaultIfEmpty(new myObject {fieldname = 0})
.FirstOrDefault().fieldname;
如果我理解正确,您可以尝试以下方法:
int thisvalue = context.tablename
.Where(q => q.ID == id)
.OrderByDescending(q => q.fieldname)
.Select(q => q.fieldname)
.FirstOrDefault();
或
在调用FirstOrDefault()之前选择q.fieldname将使SQL只返回第一个items fieldname(而不是整个第一行)
另外,q.ID是唯一的吗?如果是这样,则不需要按字段名排序,可以使用SingleOrDefault而不是FirstOrDefault。Single确保只有一个元素,而First确保至少有一个元素。应该使用Single来说明您的假设,它对于更多自文档化代码来说是唯一的
int thisvalue = context.tablename
.Where(q => q.ID == id)
.Select(q => q.fieldname)
.SingleOrDefault();
这看起来是正确的,奇怪的是OrderByDescending在本例中似乎没有达到预期效果。如果我在没有.First()的情况下进行调试,我将得到一个升序列表…仍在使用它。为了回答您的最后一个问题,q.ID不是唯一的。这些是详细记录,我正在检索“fieldname”(用于排序的序列号)的最大值,然后递增该值并将其分配给新记录。您的第二个示例正是我要查找的。它们在功能上看起来都是一样的,不知道为什么第一个不起作用。谢谢你的建议,我看到Berkelybross首先回答了这个问题,它更接近我开始的答案。不过,我喜欢DefaultIfEmpty示例。