【问题标题】:LINQ select returning NULL when creating a new objectLINQ 选择在创建新对象时返回 NULL
【发布时间】:2020-03-28 23:10:19
【问题描述】:

我正在使用 LINQ 在新对象中返回结果列表。

最终结果应该是:

var test = context.Playarea
            .Include(x => x.Cats)
            .Where(x => x.Cats.Any())
            .SelectMany(x => x.Cats.Select(y => new MyClass(x.Id, y.Name)));

我已经测试了以下内容,它整齐地返回了一个名称列表。

var test = context.Playarea
            .Include(x => x.Cats)
            .Where(x => x.Cats.Any())
            .SelectMany(x => x.Cats.Select(y => y.Name));

如果我尝试将它转换为一个非常简单的对象,但我得到一个 NULL 异常?

public class MyClass
{
    public MyClass(string name)
    {
        Name = name;
     }

    public string Name { get; set; }
}


var test = context.Playarea
            .Include(x => x.Cats)
            .Where(x => x.Cats.Any())
            .SelectMany(x => x.Cats.Select(y => new MyClass(y.Name)));

没有什么可以为 NULL,所以我不明白它是如何得到这个的?

GetEnumerator(): Exception of type 'System.NullReferenceException' was thrown

我在其他地方使用相同的类,这里唯一的区别是使用 SelectMany()。

匿名对象也可以正常工作:

var test = context.Playarea
                .Include(x => x.Cats)
                .Where(x => x.Cats.Any())
                .SelectMany(x => x.Cats.Select(y => new { Id = x.Id, Name = y.Name } ));

【问题讨论】:

  • SelectMany 永远不会返回null,但是您如何观察结果?由于延迟执行,调试器在显示准确结果方面是出了名的差。
  • 我在 JetBrains Rider 中使用断点。我的代码返回一个有效的字符串列表,但它无法处理创建一个新的 MyClass。
  • 我会使用ToList() 创建一个实际的集合来查看结果。这将比调试器更明确。
  • 我尝试在我的测试中使用 ToList() 并且它确实创建了一个字符串列表。如果我在尝试创建类时这样做,我只会收到 500 错误。
  • 必须是我们看不到代码的实体类之一。旁注:您可以删除Include

标签: linq asp.net-core-3.0


【解决方案1】:

异常堆栈跟踪显示异常源自 EF Core 基础架构

at Microsoft.EntityFrameworkCore.Query.QueryableMethodTranslatingExpressionVisitor.MemberAccessShiftingExpressionVisitor.VisitExtension(Expression node)

这清楚地表明了 EF Core 错误。

请注意,仅客户端支持使用构造函数的投影,即仅当它是最终查询操作时,因此该错误很可能是由 EF Core 3.x 查询处理管道中的缺失案例引起的。

不管怎样,你还没有提出具体的问题,只是显示了问题和症状,所以你真的应该去https://github.com/dotnet/efcore/issues报告。

如果您正在寻找解决方法,我可以建议以下两个。

如果你只需要y,你可以移动Select SelectMany之后,例如

.SelectMany(x => x.Cats).Select(y => new MyClass(y.Name));

如果您同时需要 xy,或者一般情况下,您可以将 Select 替换为带有结果选择器的 SelectMany 重载,例如

.SelectMany(x => x.Cats, (x, y) => new MyClass(x.Id, y.Name))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-31
    • 1970-01-01
    • 2021-12-03
    • 1970-01-01
    • 2021-12-25
    • 1970-01-01
    相关资源
    最近更新 更多