DefaultIfEmpty().Max() 仍然抛出 'Sequence contains no elements.'
DefaultIfEmpty().Max() still throws 'Sequence contains no elements.'
在我将我的项目更新到 dotnet core 3.0RC1(可能也在预览版 9 中)之后,我的代码曾经可以工作
var value = context.Products.Where(t => t.CategoryId == catId).Select(t => t.Version).DefaultIfEmpty().Max();
开始投掷
System.InvalidOperationException: Sequence contains no elements
。有问题的 table 是空的。
如果我添加 ToList()
使其看起来像这样 DeafultIfEmpty().ToList().Max()
,它将再次开始工作。找不到有关重大更改的任何信息。当我运行
var expectedZero = new List<int>().DefaultIfEmpty().Max();
它工作正常。这让我觉得 EF Core 可能有问题。然后我使用完全相同的设置在 xUnit 中创建了测试,但是测试通过了(table 也是空的,使用 InMemoryDatabase 而不是实时 SQL 服务器实例)。
我真的很纳闷。
相关堆栈跟踪:
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)
编辑
产品class:
[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; }
}
第二次编辑
Sql 由 ef core 制作
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
所以我打开了 issue in EF Core repo 并得到了答案。显然这是当前的行为,以后可能会改变。
建议使用以下方法
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()。
在我将我的项目更新到 dotnet core 3.0RC1(可能也在预览版 9 中)之后,我的代码曾经可以工作
var value = context.Products.Where(t => t.CategoryId == catId).Select(t => t.Version).DefaultIfEmpty().Max();
开始投掷
System.InvalidOperationException: Sequence contains no elements
。有问题的 table 是空的。
如果我添加 ToList()
使其看起来像这样 DeafultIfEmpty().ToList().Max()
,它将再次开始工作。找不到有关重大更改的任何信息。当我运行
var expectedZero = new List<int>().DefaultIfEmpty().Max();
它工作正常。这让我觉得 EF Core 可能有问题。然后我使用完全相同的设置在 xUnit 中创建了测试,但是测试通过了(table 也是空的,使用 InMemoryDatabase 而不是实时 SQL 服务器实例)。
我真的很纳闷。 相关堆栈跟踪:
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)
编辑
产品class:
[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; }
}
第二次编辑 Sql 由 ef core 制作
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
所以我打开了 issue in EF Core repo 并得到了答案。显然这是当前的行为,以后可能会改变。
建议使用以下方法
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()。