空时Linq查询不返回null

Posted

技术标签:

【中文标题】空时Linq查询不返回null【英文标题】:Linq query NOT returning null when empty 【发布时间】:2018-03-05 13:58:39 【问题描述】:

我正在使用 .NetCore 1.1.2。当我将生成的操作用于GET 操作时,它应该在数据库上找不到任何内容时返回 null,但 Null 验证不起作用。

我尝试使用 Single() 而不是 SingleOrDefault 并使用 try catch 来处理抛出的异常,但这似乎不是一个优雅的解决方案。

也许是 .net 版本?

public IActionResult Success(string token)

    var paymentMade = _context.Payments
            .SingleOrDefaultAsync(m => m.StripeToken == token);

    if (paymentMade == null)
    
        return NotFound(); //this never gets fired when empty
    

    return View();

【问题讨论】:

我想你在 FirstOrDefault 之后? 您是如何定义付款的? 嘿,不要使用Async - 检查paymentMate 变量的类型。使用同步版本或await FirstOrDefault@user12345 相同 你正在使用异步版本,而不是等待它。 【参考方案1】:

您当前的方法存在两个问题。一个是您选择的方法,另一个是您尝试在同步上下文中使用它,即使它是异步的。

首先SingleOrDefaultAsync和其他异步方法一样,不返回任何有用的值,而是Task,这是一个代表异步操作的对象。要获得上述操作的结果,您必须await它。

为此,您应该使您的方法异步或同步运行任务(不推荐,因为它会阻塞线程直到它完成)。或者,您也可以简单地使用该方法的同步版本SingleOrDefault

修改为异步的方法如下所示:

public async Task<IActionResult> Success(string token)

    var paymentMade = await _context.Payments.SingleOrDefaultAsync(m => m.StripeToken == token);

    if (paymentMade == null)
    
        return NotFound();
    

    return View();

同步运行任务如下所示:

public IActionResult Success(string token)

    var paymentMade = _context.Payments.SingleOrDefaultAsync(m => m.StripeToken == token).Result;

    if (paymentMade == null)
    
        return NotFound();
    

    return View();

但是,您可能会遇到另一个问题。根据数据类型,SingleOrDefault 和其他此类方法(如 FirstOrDefault)可能永远返回 null。对于所有不可为空的内置类型(例如布尔值、整数等)都是这种情况。如果您想要一种适用于所有情况的替代方法,那么 try-catch 是您最好的选择:

try

    var paymentMade =  _context.Payments.First(m => m.StripeToken == token);

catch (InvalidOperationException)

    return NotFound();

如果你不想这样做,那么考虑像这样拆分:

var temp = _context.Payments.Where(m => m.StripeToken == token);
if (!temp.Count == 0)

    return NotFound();

【讨论】:

【参考方案2】:

这是因为SingleOrDefaultAsync实际上是返回任务。你应该这样做。

public async Task<IActionResult> Success(string token)


    var paymentMade = await _context.Payments
        .SingleOrDefaultAsync(m => m.StripeToken == token);

    if (paymentMade == null)
    
        return NotFound(); //this never gets fired when empty
    

    return View();

【讨论】:

【参考方案3】:

如果您不想要列表,请尝试使用 FirstOrDefault,而不是 SingleOrDefault,并且取决于对象 paymentMade 的数据类型。

如果您想要一个列表,请使用 .Where(m => m.StripeToken == token).ToList(),并在您的 if verify paymentMade.Count==0 中。

看看这个LINQ: When to use SingleOrDefault vs. FirstOrDefault() with filtering criteria。

【讨论】:

【参考方案4】:

您正在使用 SingleOrDefault()async 版本:SingleOrDefaultAsync(),并且没有“等待”它,因此您在 paymentMade 变量中实际拥有的是一个等待对象,它不会是无所谓。

有几种方法可以解决:

1- 你做你的动作async 并使用await,像这样:

public async IActionResult Success(string token)

    var paymentMade = await _context.Payments
        .SingleOrDefaultAsync(m => m.StripeToken == token);

    if (paymentMade == null)
    
        return NotFound(); //this never gets fired when empty
    

    return View();

2- 您可以调用SingleOrDefault() 方法的非异步(标准)版本,您的代码将如下所示:

public IActionResult Success(string token)

    var paymentMade = _context.Payments
        .SingleOrDefault(m => m.StripeToken == token);

    if (paymentMade == null)
    
        return NotFound(); //this never gets fired when empty
    

    return View();

选择最适合你的那个

【讨论】:

你最后一个例子和另一个一样 你仍然需要删除那个等待

以上是关于空时Linq查询不返回null的主要内容,如果未能解决你的问题,请参考以下文章

如何在源集合为空时强制 LINQ Sum() 返回 0

LINQ 查询总是返回 Null

使用linq进行查询,结果为空时,是怎么判断的呢?

Linq查询where子句返回null

当未找到结果时,其中 First() 似乎返回 null 的 Linq 查询

spring boot加mybatis使用Map返回时,当值为空时属性也会没有(转)