使用Single和SingleOrDefault之间的逻辑区别是什么?

时间:2017-09-07 05:04:11

标签: c# asp.net-mvc entity-framework asp.net-mvc-5

我不知道我应该在哪里使用Single以及我应该在哪里使用SingleOrDefault。我理解两者的定义。

  1. 它总会返回一行。

  2. 如果找不到行,我将收到例外。

  3. 如果找到多行,我将收到异常。

  4. 的SingleOrDefault:

    1. 它将始终返回一行,如果未找到,则返回默认值(What is the meaning of this DEFAULT VALUE").

    2. 如果多行则异常。

    3. 问题1:&#34的含义是什么;它将返回默认值"

      问题2:何时使用Single以及何时使用SingleOrDefault。

      我有一个删除功能,我的代码如下:

      [HttpPost]
      [ValidateAntiForgeryToken]
      public ActionResult Delete(int resumeId)
      {
          var r = _context
              .Resumes
              .Where(c => c.ResumeId == resumeId).SingleOrDefault();
          _context.Resumes.Remove(r);
          _context.SaveChanges();
      
          return RedirectToAction("ResumeCenter");
      }
      

      我只是盲目地把SingleOrDefault放到任何地方(我在ATMOST期待一个值),请告诉我一个真实世界的场景,我应该使用" Single"我应该使用" SingleOrDefault"。

5 个答案:

答案 0 :(得分:3)

这几乎(但不完全)是一种风格问题。你更喜欢哪一个?

try
{
    var x = someEnumerable.Single();
}
catch (InvalidOperationException)
{
    //Did not contain exactly one record
}

的SingleOrDefault:

var y = someEnumerable.SingleOrDefault();
if (y == null)
{
    //Did not contain exactly one record
}

基于异常的方法是一个更多的编码,但它很好,因为可以允许异常冒泡。话虽这么说,我通常使用XXXOrDefault变体来避免堆栈展开,这可能会导致性能下降。作为一项规则,您应该避免在期望行为时抛出异常。

P.S。可以使用keyword default(type)获取任何类型的“默认”。对于整数,它为零,对于日期,它是MinValue,对于引用类型,它是null,等等。

P.P.S。在您的示例中,我将使用Single并允许在行丢失或存在多个行时抛出异常。否则,您最终可能会将null传递给后续的Remove方法。虽然这也会失败,但是它应该比它应该的更晚失败,导致一个欺骗性的堆栈跟踪并使故障排除变得有点棘手。

OTOH,如果变化很小,你可以做任何一个工作:

public ActionResult Delete(int resumeId)
{
    var r = _context
        .Resumes
        .Where(c => c.ResumeId == resumeId).SingleOrDefault();
    if (r == null)
    {
        return RedirectToAction("ErrorPage");
    }
    else
    {
        _context.Resumes.Remove(r);
        _context.SaveChanges();
        return RedirectToAction("ResumeCenter");
    }
}

或者

public ActionResult Delete(int resumeId)
{
    var r = _context
        .Resumes
        .Where(c => c.ResumeId == resumeId).Single();  //Error will bounce up to Application_Error or other global handler
    _context.Resumes.Remove(r);
    _context.SaveChanges();

    return RedirectToAction("ResumeCenter");
}

答案 1 :(得分:2)

正如你所说 - 如果找不到行,Single()将引发异常。 SingleOrDefault()将返回默认值(引用类型为null,int为0,字符为\ 0等。)

在以下两种情况之一中使用Single()

  1. 什么时候不应该发生这种情况,如果不这样做,就意味着出现问题。
  2. 当您处理值类型(整数,字符等)时,默认值可能是您的值系统中的有效值(例如,如果您获得了0的int但是可以不知道是不是因为你没有回来或者它是一个有效的值。
  3. 对任何其他情况使用SingleOrDefault()。 如果找不到该行,则需要将得到的值与其默认值进行比较。

    有关详细信息,请参阅default value expression.

    上指向Microsoft页面的链接

答案 2 :(得分:0)

如果您知道数据库中某些内容必须有值,请使用Single(),因为如果数据库中的“非常期望的值”不存在,您可能希望获得异常。特定员工代码的EmployeeName等数据。

当您知道员工是临时员工并且他的部门可能不会显示在主数据库中时,请使用SingleOrDefault()。但是如果部门的价值存在,它应该只有一个值。他不会立刻为多个部门工作。

http://www.c-sharpcorner.com/blogs/singleordefault-vs-firstordefault-in-linq-query1

Single() - 数据存储中预计会有一个值,您可能需要它。您想知道没有值或多个值。在这种情况下,你得到一个例外并检查。

SingleOrDefault() - 如果一条记录不存在,则为其提供一个默认值。是否有任何可用于记录的无关紧要。但它不应该是多个记录。

答案 3 :(得分:0)

当你说

时,函数名称会建议你
style = {styles.buttonStyle} // missed styles
<Text style={styles.textStyle}> Log </Text>

那意味着

  

&#34;我想要列表中的单个记录&#34;因此你得到单身   记录(第1个)&#34;

当你说

list.single();

那意味着

  

&#34;我想单曲,如果记录不存在,我会   喜欢拥有对象的默认值&#34;

完全是你的approch,你也可以去

list.SingleOrDefault();

就像单一或默认

答案 4 :(得分:0)

: 如果找到元素匹配,它将从元素集合返回单个特定元素。如果在集合中找不到该元素的匹配项,则抛出异常。

<强>的SingleOrDefault : 如果找到元素匹配,它将从元素集合返回单个特定元素。如果在集合中找到该元素的多个匹配项,则抛出异常。如果未找到集合中该元素的匹配项,则返回默认值。