繁体   English   中英

EF SqlQuery尝试映射对象属性,即使它归因于[NotMapped]

[英]EF SqlQuery tries to map object property, even though it's attributed [NotMapped]

我有一个存储过程,我使用context.Database.SqlQuery<MyObject>("MyProc")

MyObject具有只读属性:

[NotMapped]
public bool IsSomething { get { return this.otherproperty == "something"; } }

所以我得到错误:

System.IndexOutOfRangeException:IsSomething at System.Data.ProviderBase.FieldNameLookup.GetOrdinal etc

这是因为MyProc在结果列中没有IsSomething (我100%肯定这可能是原因)。

它不应该忽略它,因为它是[NotMapped] 我是否需要为SqlQuery设置其他内容?

为了让事情变得更加奇怪,我只在生产中看到它,从Stackify的日志中看,并且页面似乎正确加载而浏览器没有任何错误。

根据文件

Database.SqlQuery<TElement> Method (String, Object[])

创建将返回给定泛型类型的元素的原始SQL查询。 类型可以是具有与查询返回的列的名称匹配的属性的任何类型,也可以是简单的基本类型。 该类型不必是实体类型。 即使返回的对象类型是实体类型,上下文也不会跟踪此查询的结果.....

强调我的

它正在查询从查询​​中返回的IsSomething如错误消息中的System.Data.ProviderBase.FieldNameLookup.GetOrdinal所示。

因为该列不存在,您将获得IndexOutOfRangeException

它不应该忽略它,因为它是[NotMapped]

不会。它会忽略对象上存在的任何属性,包括[NotMapped] 请参阅上面引用的引用

我是否需要为SqlQuery设置其他内容?

我建议创建另一个对象,只有属性匹配/映射到过程的预期结果,并使用它作为SqlQuery调用的泛型参数。

为了让事情变得更加奇怪,我只在生产中看到它,从Stackify的日志开始,页面似乎正确加载而没有任何错误

我不熟悉Stackify日志,但根据我对EF6的了解,我会推测并说这是误报日志。

在这方面,文件并不十分清楚。 首先,实体和非实体SqlQuery结果类型由不同的代码分支处理。 虽然两个转换都使用CLR属性名作为列名(即不考虑实体类型的列名映射),但NotMapped类型的忽略( NotMapped )属性确实从结果中排除

此外,有问题的IndexOutOfRangeException被EF代码捕获并转换为另一个异常( EntityCommandExecutionException ),可以从相关方法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与真正的异常,我会说你可以安全地忽略该日志。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM