實體框架核心中的存儲過程“枚舉產生無結果”錯誤

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

在我使用EF Core 1.1的ASP.NET Core 1.1項目中,我試圖按照這篇官方MSDN文章這篇 文章調用SQL Server存儲過程。但是我在以下代碼中的While loop中遇到了上述錯誤。

我已經使用SQL Server Profiler驗證了存儲過程是否成功調用了

DbDataReader oReader = await cmd.ExecuteReaderAsync();

line,當我在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;
}

一般承認的答案

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),


Related

許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow
許可下: CC-BY-SA with attribution
不隸屬於 Stack Overflow