首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >DefaultIfEmpty().Max()仍然抛出“序列不包含元素。”

DefaultIfEmpty().Max()仍然抛出“序列不包含元素。”
EN

Stack Overflow用户
提问于 2019-09-21 10:45:41
回答 3查看 3K关注 0票数 11

在我将我的项目更新到DotNetCore3.0RC1(可能也在preview9中)之后,我的代码就开始工作了

代码语言:javascript
运行
复制
var value = context.Products.Where(t => t.CategoryId == catId).Select(t => t.Version).DefaultIfEmpty().Max();

开始扔System.InvalidOperationException: Sequence contains no elements。这张桌子是空的。

如果我添加了ToList(),所以它看起来像这个DeafultIfEmpty().ToList().Max(),那么它又开始工作了。无法找到任何有关重大更改的信息。当我跑的时候

代码语言:javascript
运行
复制
var expectedZero = new List<int>().DefaultIfEmpty().Max();

效果很好。这让我觉得EF核心可能出了什么问题。然后,我用完全相同的设置在xUnit中创建了测试,但是测试正在通过(表也是空的,使用InMemoryDatabase而不是活动Server实例)。

我真的很困惑。相关堆栈跟踪:

代码语言:javascript
运行
复制
System.InvalidOperationException: Sequence contains no elements.
   at int lambda_method(Closure, QueryContext, DbDataReader, ResultContext, int[], ResultCoordinator)
   at bool Microsoft.EntityFrameworkCore.Query.RelationalShapedQueryCompilingExpressionVisitor+QueryingEnumerable<T>+Enumerator.MoveNext()
   at TSource System.Linq.Enumerable.Single<TSource>(IEnumerable<TSource> source)
   at TResult Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.Execute<TResult>(Expression query)
   at TResult Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryProvider.Execute<TResult>(Expression expression)
   at TSource System.Linq.Queryable.Max<TSource>(IQueryable<TSource> source)
   at ... (my method that run the code)

编辑

产品类别:

代码语言:javascript
运行
复制
   [Table("tmpExtProduct", Schema = "ext")]
    public partial class Product
    {
        [Key]
        [DatabaseGenerated(DatabaseGeneratedOption.None)]
        public int Version { get; set; }

        [Column(TypeName = "datetime")]
        public DateTime ImportDate { get; set; }

        public int CategoryId { get; set; }
        public string Description { get; set; }

        [ForeignKey(nameof(Ext.Category))]
        public int CategoryId { get; set; }        

        [InverseProperty(nameof(Ext.Category.Products))]
        public virtual Category Category { get; set; }
    }

第二次编辑由ef核生成的 Sql

代码语言:javascript
运行
复制
exec sp_executesql N'SELECT MAX([t0].[Version])
FROM (
    SELECT NULL AS [empty]
) AS [empty]
LEFT JOIN (
    SELECT [p].[Version], [p].[CategoryId], [p].[ImportDate], [p].[Description]
    FROM [ext].[tmpExtProduct] AS [p]
    WHERE (([p].[CategoryId] = @__categoryId_0) AND @__categoryId_0 IS NOT NULL)
) AS [t0] ON 1 = 1',N'@__categoryId_0 int',@__categoryId_0=5
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-09-25 05:05:38

于是我打开EF核心回购中的问题,得到了答案。显然,这是目前的行为,这可能会改变以后。

建议采用以下方法

代码语言:javascript
运行
复制
var valueFail = context.Products.Where(t => t.CategoryId == catId)
                .GroupBy(e => 1)
                .Select(t => t.Max(e => e.Version))
                .ToList()[0];

这比我的解决方案DeafultIfEmpty().ToList().Max()更好,因为它将执行所有的工作服务器端,而我的解决方案将在客户机上计算Max()。

票数 5
EN

Stack Overflow用户

发布于 2022-06-09 03:56:21

一个解决办法可能是使用OrderByFirstOrDefault组合。

代码语言:javascript
运行
复制
var value = context.Products
    .Where(t => t.CategoryId == catId)
    .OrderByDescending(t => t.Version)
    .Select(t => t.Version)
    .FirstOrDefault();

我通常使用这种方法,很少使用Max()

票数 1
EN

Stack Overflow用户

发布于 2022-06-09 02:49:47

通过米基自答,异常仍然会被抛出,但是这个异常消息变成了"Nullable对象必须有一个值“。因为当序列为空时返回为null,但不能将null分配给值类型int

正确的做法是将目标值类型转换为Nullable<>,它将返回null,而不是抛出“序列不包含任何元素”。或者"Nullable对象必须有一个值“。当序列为空时出现异常。

代码语言:javascript
运行
复制
var value = context.Products
    .Where(t => t.CategoryId == catId)
    .Select(t => (int?)t.Version)
    .Max();

现在,变量value的类型是Nullable<int>,请记住检查它是否为空。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58039509

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档