1

因此,我在 NOSQL 数据库上运行 linq 查询,如果存在具有该 ID 的对象,则应仅返回单个对象,如果不存在则不返回任何对象,但数据库中可能存在具有相同 ID 的两个对象(如果其他人搞砸了起来。)目前我的实现如下:

(from c in [IQueryableThing] where c.Id.Equals(id)).ToList().First()

我也考虑过替代方案

(from c in [IQueryableThing] where c.Id.Equals(id)).Single()

我假设 .Single() 更快,但我担心这些都不能处理数据库中没有具有正确 id 的对象的情况。我不在乎是否有多个返回。我只想要其中之一。最终我会实现一些东西来返回最近修改的。

基本上我的问题是解决这个问题的最佳方法是将可查询对象转换为单个实例的方法是处理没有具有正确 id 的对象并且有多个具有正确 id 的对象的情况。

4

6 回答 6

14

听起来你只是想打电话FirstOrDefault(),这正是名字所暗示的。
Default意味着null

你不应该打电话ToList();这将不必要地从数据库中下载所有结果。

于 2013-10-14T18:55:36.380 回答
5

使用IQueryable.Single效率更高:

  • 调用ToList枚举整个结果集并将每个项目存储在内存中的单个连续数组中。然后First只从数组中获取第一项。
  • 调用IQueryable.Single只计算列表中的第一项,如果没有返回任何项,则抛出异常。然后它检查结果集中是否还有其他项目,如果有则抛出异常。

如果您想处理集合中不存在符合您的条件的项目,但不关心是否有多个项目的情况,我强烈建议您使用FirstOrDefault

var result = (from c in [IQueryableThing] where c.Id.Equals(id)).FirstOrDefault();
if (result == null)
{
    // no items found
}

这将转换为TOP 1SQL 中的 a,并简单地返回结果集中的第一项,或者如果结果集为空,它将简单地返回null(或者如果您正在处理结构,则返回默认值)。

于 2013-10-14T18:55:48.537 回答
3

.ToList()不应该有所作为,它只会将可查询的内容枚举到内存列表中。对于您的情况,您有多种选择。您展示的两个行为非常不同:

  • .First()- 这将返回枚举中的第一个元素,如果没有则抛出异常。
  • .Single()- 这将返回枚举中唯一的元素,如果没有元素有多个元素,则抛出异常。
  • .FirstOrDefault()null- 这将返回枚举中的第一个元素,如果没有,则返回默认值(用于引用类型)。
  • .SingleOrDefault()- 这将返回枚举中唯一的元素,如果没有则返回默认值(null用于引用类型),如果有多个抛出异常。

听起来你想使用.FirstOrDefault(). 检查结果是否为null. 如果是,则没有匹配的元素。如果不是,则您拥有第一个匹配元素。

于 2013-10-14T18:56:45.643 回答
2

你应该使用.FirstOrDefault(c => c.ID.Equals(id));

如果没有找到(默认是null类)或找到的第一个,它将返回默认值。

于 2013-10-14T18:56:26.867 回答
2

我相信你正在寻找Enumerable.FirstOrDefault

返回序列的第一个元素,如果序列不包含任何元素,则返回默认值。

于 2013-10-14T18:55:31.150 回答
0

如果您确定存在 ONE 且仅 ONE 项目,并且您将要使用 Single()

如果您不确定使用 First() 或 FirstOrDefault() 将返回多少项目。

不同之处在于,如果存在多个项目,Single() 将引发异常。如果您想在没有唯一约束的数据库上捕获插入错误等,则非常有用。

于 2013-10-14T19:04:43.380 回答