【问题标题】:Stored procedure in Entity Framework Core "enumeration yielded no results" errorEntity Framework Core 中的存储过程“枚举未产生结果”错误
【发布时间】:2017-05-13 06:03:48
【问题描述】:

在我的带有 EF Core 1.1 的 ASP.NET Core 1.1 项目中,我试图按照 official MSDN articlethis post 调用 SQL Server 存储过程。但是我在以下代码中的While loop 中遇到了上述错误。

我已经使用 SQL Server Profiler 验证了存储过程在

DbDataReader oReader = await cmd.ExecuteReaderAsync();

行,当我在 SSMS 中运行捕获的 SQL 调用时,它确实返回了正确数量的记录。

那么为什么会出现错误以及如何解决呢?由于此错误,应用无法在视图中返回结果。

注意:您可能已经注意到我使用 ADO.NET 和 EF 提供的数据库连接 [参考:上述 MSDN 文章]

public async Task<List<CustOrderViewModel>> getOrderReport(int SelectedYear, byte SelectedOrderType)
{
    List<CustOrderViewModel> lstOrderReport = new List<CustOrderViewModel>();

    using (SqlConnection conn = (SqlConnection)_context.Database.GetDbConnection())
    {
        await conn.OpenAsync();

        using (SqlCommand cmd = conn.CreateCommand())
        {
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.CommandText = "getOrderReport_SP";
            cmd.Parameters.AddWithValue("@year", SelectedYear);
            cmd.Parameters.AddWithValue("@orDerType", SelectedProjType);

            DbDataReader oReader = await cmd.ExecuteReaderAsync();

            if (oReader.HasRows)
            {
                while (await oReader.ReadAsync())
                {
                    var row = new CustOrderViewModel
                    {
                        SelectedOrderYr = oReader.GetInt32(0),
                        OrderNumber = oReader.GetString(1),
                        OrderDesctiption = oReader.GetString(3),
                        OrderType = oReader.GetByte(8)
                    };
                    lstOrderReport.Add(row);
                }
            }

            oReader.Dispose();
        }
    }

    return lstOrderReport;
}

【问题讨论】:

  • 您的代码中的lstPADBReport 是什么?您从哪里得到上述异常?
  • @IvanStoev 这是帖子中的错字。我已经纠正了。是lstOrderReport.Add(row); 但错误是一样的。
  • 我明白了。哪一行抛出异常?我们可以看到异常堆栈跟踪吗?
  • 好吧,ORM 通常对你隐藏空处理,但是当你在低级别工作时(直接使用 ADO.NET),你应该自己处理。例如,如果OrderDesctiption 列可以为空,那么您应该使用类似OrderDesctiption = !oReader.IsDBNull(3) ? oReader.GetString(3) : null 的内容。并对每个可为空的列执行相同的操作。
  • @IvanStoev 您的上述评论解决了这个问题(谢谢)。您的第一条评论实际上帮助我找到了问题的原因。为了每个人的利益,您可能希望将上述评论作为回复,我会将其标记为答案。

标签: c# asp.net-core ado.net entity-framework-core ado.net-entity-data-model


【解决方案1】:

ORM 和 Micro ORM 的一个好处是它们通常会为您处理可为空的数据。

但是,在低级别工作时(直接使用 ADO.NET),您需要自己处理所有事情。其中DbDataReader 意味着您应该在调用具体的GetXXX 方法之前使用IsDBNull 方法。

因此,如果 OrderDesctiption 列可以为空,为避免异常,您应该使用类似这样的内容

OrderDesctiption = !oReader.IsDBNull(3) ? oReader.GetString(3) : null,

类似于任何其他可为空的类型列。

由于在很多地方这样做很烦人,我宁愿创建一个像这样的小型辅助扩展方法实用程序:

public static class DataReaderExtenstions
{
    public static string GetNString(this DbDataReader reader, int ordinal)
    {
        return !reader.IsDBNull(ordinal) ? reader.GetString(ordinal) : null;
    }
    public static int? GetNInt32(this DbDataReader reader, int ordinal)
    {
        return !reader.IsDBNull(ordinal) ? reader.GetInt32(ordinal) : (int?)null;
    }
    // Similar for Int16, Byte, Decimal, Double, DateTime etc.
}

只需在需要的地方使用N(可为空)版本:

OrderDesctiption = oReader.GetNString(3),

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-21
    • 2015-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多