Asp.net mvc 4 检索单个字段值时的FirstOrDefault()

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值

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示例。