我有一个用context.Database.SqlQuery<MyObject>("MyProc")
MyObject
有一个只读属性:
[NotMapped]
public bool IsSomething { get { return this.otherproperty == "something"; } }
所以我收到错误:
System.IndexOutOfRangeException:IsSomething 在System.Data.ProviderBase.FieldNameLookup.GetOrdinal等
这是因为MyProc在结果列中没有IsSomething
(我100%肯定可能是原因)。
它不应该忽略它,因为它[NotMapped]
?我是否需要为SqlQuery
设置其他内容?
为了让事情变得更加奇怪,我只能在生产中看到它,从Stackify的日志中看,并且页面似乎正确加载而浏览器没有任何错误。
答案 0 :(得分:4)
Database.SqlQuery<TElement> Method (String, Object[])
创建一个原始SQL查询,该查询将返回给定泛型类型的元素。 类型可以是任何类型,其属性与查询返回的列的名称相匹配,也可以是简单的基本类型。该类型不必是实体类型。即使返回的对象类型是实体类型,也不会被上下文跟踪此查询的结果.....
强调我的
它正在查看错误消息中IsSomething
指示的System.Data.ProviderBase.FieldNameLookup.GetOrdinal
查询返回的读者。
由于该列不存在,您将获得IndexOutOfRangeException
。
它不应该忽略它,因为它是
[NotMapped]
?
没有。它忽略对象上存在的任何属性,包括[NotMapped]
。请参阅上面引用的引用
我是否需要为SqlQuery设置其他内容?
我建议创建另一个对象,其中只有属性匹配/映射到过程的预期结果,并将其用作SqlQuery
调用的泛型参数。
答案 1 :(得分:2)
为了让事情变得更加奇怪,我只在生产中看到它,从Stackify的日志中看,并且页面似乎正确加载而没有任何错误
我不熟悉Stackify日志,但根据我对EF6的了解,我会推测并说这是误报日志。
在这方面,文件并不十分清楚。首先,实体和非实体SqlQuery
结果类型由不同的代码分支处理。虽然两个翻译都使用CLR属性名作为列名(即不考虑实体类型的列名映射),但实体类型的忽略(NotMapped
)属性确实是按预期从结果中排除。
此外,有问题的IndexOutOfRangeException
被EF代码捕获并转换为其他异常(EntityCommandExecutionException
),可以从相关方法的source code GetMemberOrdinalFromReader
中看到}:
// <summary>
// Given a store datareader and a member of an edmType, find the column ordinal
// in the datareader with the name of the member.
// </summary>
private static int GetMemberOrdinalFromReader(
DbDataReader storeDataReader, EdmMember member, EdmType currentType,
Dictionary<string, FunctionImportReturnTypeStructuralTypeColumnRenameMapping> renameList)
{
int result;
var memberName = GetRenameForMember(member, currentType, renameList);
if (!TryGetColumnOrdinalFromReader(storeDataReader, memberName, out result))
{
throw new EntityCommandExecutionException(
Strings.ADP_InvalidDataReaderMissingColumnForType(
currentType.FullName, member.Name));
}
return result;
}
和TryGetColumnOrdinalFromReader
:
// <summary>
// Given a store datareader and a column name, try to find the column ordinal
// in the datareader with the name of the column.
// </summary>
// <returns> true if found, false otherwise. </returns>
private static bool TryGetColumnOrdinalFromReader(DbDataReader storeDataReader, string columnName, out int ordinal)
{
if (0 == storeDataReader.FieldCount)
{
// If there are no fields, there can't be a match (this check avoids
// an InvalidOperationException on the call to GetOrdinal)
ordinal = default(int);
return false;
}
// Wrap ordinal lookup for the member so that we can throw a nice exception.
try
{
ordinal = storeDataReader.GetOrdinal(columnName);
return true;
}
catch (IndexOutOfRangeException)
{
// No column matching the column name found
ordinal = default(int);
return false;
}
}
基于以上内容以及缺少具有真实异常的repro,我会说你可以安全地忽略该日志。