空时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的主要内容,如果未能解决你的问题,请参考以下文章