c# - 运行 SqlQuery EF 时 FieldNameLookup.GetOrdinal 中的索引超出范围异常
问题描述
当运行这样的代码时,我们最终会得到一个IndexOutOfRange异常:
result.Data = dbOptima.Database.ExecuteStoredProcedure(
task,
StoredProcedureValues.PROC_GET_TASKS).ToList();
,在哪里ExecuteStoredProcedure
执行以下操作:
public static IEnumerable<TResult> ExecuteStoredProcedure<TResult>(this Database database, IStoredProcedure<TResult> procedure, string procedureName)
{
var parameters = CreateSqlParametersFromProperties(procedure);
var format = CreateSPCommand<TResult>(parameters, procedureName);
return database.SqlQuery<TResult>(format, parameters.Cast<object>).ToArray());
}
我们无法在本地重现该问题,但使用Application Insights经常会注册异常。以下是调用堆栈摘录:
System.IndexOutOfRangeException:
at System.Data.ProviderBase.FieldNameLookup.GetOrdinal (System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Data.SqlClient.SqlDataReader.GetOrdinal (System.Data, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Data.Entity.Core.Query.InternalTrees.ColumnMapFactory.TryGetColumnOrdinalFromReader (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Data.Entity.Core.Query.InternalTrees.ColumnMapFactory.CreateColumnMapFromReaderAndClrType (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Data.Entity.Core.Objects.ObjectContext.InternalTranslate (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQueryInternal (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Data.Entity.Core.Objects.ObjectContext+<>c__DisplayClass65`1.<ExecuteStoreQueryReliably>b__64 (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Data.Entity.Core.Objects.ObjectContext.ExecuteInTransaction (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Data.Entity.Core.Objects.ObjectContext+<>c__DisplayClass65`1.<ExecuteStoreQueryReliably>b__63 (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Data.Entity.SqlServer.DefaultSqlExecutionStrategy.Execute (EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQueryReliably (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Data.Entity.Core.Objects.ObjectContext.ExecuteStoreQuery (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Data.Entity.Internal.LazyEnumerator`1.MoveNext (EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Collections.Generic.List`1..ctor (mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
at System.Linq.Enumerable.ToList (System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089)
我们尝试通过以下方式在本地重现该问题:
- 使存储过程失败。
- 使存储过程返回 0 个结果。
- 通过重命名某些模型属性导致映射问题。
没有成功。
通常,当您使用ADO.NET时,由于数据读取器中的映射错误而发生此错误,但情况并非如此,因为我们使用EF 6并且它并不总是发生,因此我们无法真正找到问题所在。
解决方案
该问题与将存储过程的结果与声明为与存储过程的输出绑定的模型绑定有关。
如果存储过程检索到的列多于模型具有的属性,即使满足模型(因为所有属性都可以与存储过程输出的列匹配),内部也会引发异常,因为模型没有存储一些存储过程输出值的属性。
所以,这可以通过两种方式解决:要么
- 在模型中添加属性以包含存储过程的列,或者
- 删除存储过程输出中不必要的列。
第二种方法通常更好,因为这个问题表明存储过程返回的某些数据不再需要,因此删除存储过程中不需要的代码会更干净,性能更高。
推荐阅读
- javascript - 对象迭代跳过两位数?
- c++ - C ++派生类仅使用继承的基构造函数的一部分
- python - numpy.corrcoef 评估与 y 标签输出相关的最佳 x 或特征列
- flask - 我如何在不同的端口上运行 Swagger UI,然后在 Flask 中的主 App 端口上运行?就像 Swagger 在 8080 上运行,主应用在 8081 上运行
- excel - 从引用中删除前导零
- python - 如何将曲线拟合到包含 NaN 值的 Excel 文件的数据
- javascript - 如何在带有scrollspy的导航系统中保持css中的元素处于活动状态?
- lisp - Common Lisp 排序函数从原始列表中删除一个元素
- python - 使用 sklearn 预测离散值
- javascript - 在反应挂钩中同步调用函数后数据未加载?