Entity Framework 核心中的存储过程 "enumeration yielded no results" 错误
Stored procedure in Entity Framework Core "enumeration yielded no results" error
在我使用 EF Core 1.1 的 ASP.NET Core 1.1 项目中,我试图通过遵循此 official MSDN article and 来调用 SQL 服务器存储过程。但是我在以下代码的 While loop
中遇到了上述错误。
我已经使用 SQL Server Profiler 验证存储过程在
处被成功调用
DbDataReader oReader = await cmd.ExecuteReaderAsync();
行,当我 运行 在 SSMS 中捕获的 SQL 调用时,它会 return 正确的记录数。
那么为什么我会收到错误消息以及如何解决它?由于此错误,应用无法 return 视图中的结果。
注意:您可能已经注意到我正在使用 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 和微型 ORM 的好处之一是它们通常会为您处理可为 null 的数据。
但是,在低级别工作时(直接使用ADO.NET),您需要自己处理所有事情。 DbDataReader
意味着你应该在调用具体的 GetXXX
方法之前使用 IsDBNull
方法。
因此,如果 OrderDesctiption
列可以为 null,为避免异常,您应该使用类似这样的东西
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),
在我使用 EF Core 1.1 的 ASP.NET Core 1.1 项目中,我试图通过遵循此 official MSDN article and While loop
中遇到了上述错误。
我已经使用 SQL Server Profiler 验证存储过程在
处被成功调用DbDataReader oReader = await cmd.ExecuteReaderAsync();
行,当我 运行 在 SSMS 中捕获的 SQL 调用时,它会 return 正确的记录数。
那么为什么我会收到错误消息以及如何解决它?由于此错误,应用无法 return 视图中的结果。
注意:您可能已经注意到我正在使用 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 和微型 ORM 的好处之一是它们通常会为您处理可为 null 的数据。
但是,在低级别工作时(直接使用ADO.NET),您需要自己处理所有事情。 DbDataReader
意味着你应该在调用具体的 GetXXX
方法之前使用 IsDBNull
方法。
因此,如果 OrderDesctiption
列可以为 null,为避免异常,您应该使用类似这样的东西
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),