【问题标题】:Can't I select into list of primitive type in EF?我不能在 EF 中选择原始类型列表吗?
【发布时间】:2021-04-09 18:58:03
【问题描述】:

我想了解为什么我的代码会引发空引用异常。

DisruptionReportSteps 不为空,问题不在他们身上。我的猜测是,通过抛出 nre,EF 告诉它不能将我的布尔值投影到列表中,因为它不可能处理原始类型的集合。我说的对吗?

 var disruptionReportsQuery = _dbContext.Reports
    // query
            .Select(report => new
            {
                AreStepsFilled = new List<bool>
                {
                    report.DisruptionReportFirstStep.IsFilled,
                    report.DisruptionReportSecondStep.IsFilled,
                    report.DisruptionReportThirdStep.IsFilled,
                    report.DisruptionReportFourthStep.IsFilled,
                    report.DisruptionReportFifthStep.IsFilled,
                },
            })

如果我这样做:

var disruptionReportsQuery = _dbContext.Reports
    // query
            .Select(report => new
            {
                 IsFirstStepFilled = report.DisruptionReportFirstStep.IsFilled,
                 IsSecondStepFilled = report.DisruptionReportSecondStep.IsFilled,
                 IsThirdStepFilled = report.DisruptionReportThirdStep.IsFilled,
                 IsFourthStepFilled = report.DisruptionReportFourthStep.IsFilled,
                 IsFifthStepFilled = report.DisruptionReportFifthStep.IsFilled,
            })

它有效。

不过,我想确保我理解为什么会出现这种行为。

【问题讨论】:

  • 你用的是什么版本的ef?
  • 实体框架核心 3.1.4
  • 我对各种 EF 核心版本(3 和 5)做了完全相同的事情,我可以毫无问题地执行与您的第一个类似的查询。如果查询表达式抛出 NRE,它通常表示翻译逻辑中存在错误,因为在 C# 代码中实际上没有计算任何值。这将有助于了解更多详细信息,例如堆栈跟踪和数据库提供程序(查询提供程序)以深入了解。答案中的解决方法无助于理解。
  • @GertArnold 很抱歉,它是 3.1 EF。翻译没有太大问题。它从数据库中获取所有记录而没有任何警告,并在此之后对其进行转换。它将是 EF 5 ,它会给出一个翻译错误,因为它的工作方式不同并尝试将查询转换为 SQL。
  • @GertArnold,我正在使用 Npgsql.EntityFrameworkCore.PostgreSQL 3.1.4。我认为谢尔盖的解释是理所当然的......

标签: c# select .net-core entity-framework-core nullreferenceexception


【解决方案1】:

发生这种情况是因为您尝试使用来自查询的值而不是来自具体的值列表来初始化列表。但是查询的值始终为空,它们将在查询运行时分配(例如通过调用 ToList() 或 ToArray())。

所以如果你想创建一个基元列表,你必须首先创建一个对象列表。在此之后,您可以初始化列表。

var disruptionReports = _dbContext.Reports

            .Select(report => new
            {
                 IsFirstStepFilled = report.DisruptionReportFirstStep.IsFilled,
                 IsSecondStepFilled = report.DisruptionReportSecondStep.IsFilled,
                 IsThirdStepFilled = report.DisruptionReportThirdStep.IsFilled,
                 IsFourthStepFilled = report.DisruptionReportFourthStep.IsFilled,
                 IsFifthStepFilled = report.DisruptionReportFifthStep.IsFilled,
            }).ToList();

 var disruptionReportsList = disruptionReports
            .Select(report => new
            {
                AreStepsFilled = new List<bool>
                {
                    report.DisruptionReportFirstStep.IsFilled,
                    report.DisruptionReportSecondStep.IsFilled,
                    report.DisruptionReportThirdStep.IsFilled,
                    report.DisruptionReportFourthStep.IsFilled,
                    report.DisruptionReportFifthStep.IsFilled,
                },
            }).ToList();

【讨论】:

  • 这个问题不是关于取得结果的。这是关于了解正在发生的事情。
  • 我不喜欢猜测发生了什么。我想知道它是否有效。这将有助于理解。
  • 好吧,如果你发布它,我认为它会起作用。我知道很多人发布“试试这个”的答案,但回答者不应该先尝试自己吗?也就是说,如果它有效,它会掩盖问题并且无助于理解。 “好是伟大的敌人”。
  • 哦,我现在明白了。斯帕西博,塞雷扎。
  • 很抱歉,但这仍然只是一种解决方法,并且解释不成立。请参阅我对这个问题的评论。显然,当数组被包装成匿名类型时,查询提供者在将表达式转换为 SQL 时遇到了麻烦。无论是直接构建列表,还是包装在匿名类型中,它都只是关于表达式翻译,而不是关于值是 null
猜你喜欢
  • 1970-01-01
  • 2012-11-07
  • 2021-12-14
  • 2011-02-05
  • 1970-01-01
  • 1970-01-01
  • 2018-06-26
  • 2010-10-06
  • 1970-01-01
相关资源
最近更新 更多