25

我正在使用实体框架并更新了一个表及其存储过程,但在调用存储过程时出现以下错误。

数据读取器与指定的“FormValueModel.Valuation”不兼容。类型的成员“ValuationId”在数据读取器中没有同名的对应列。

ValuationId 是我想要自动递增的主键。

我可以执行从 SQL 管理工作室找到的存储过程,当我运行我的应用程序时,它会写入数据库,但随后会出现错误消息。

我不熟悉实体框架,只有基础知识,我认为这可能是 model.edmx 的映射问题。

在模型中重新创建和映射表和存储过程的正确过程是什么?


存储过程。

    ALTER PROCEDURE [dbo].[ValuationCreate]
    @TrackingNumber varchar(100),
    @FormMobiValuationId varchar(100),
    @ValuationPropertyId int,
    @ValuationFileName varchar(50)

AS   

SET NOCOUNT ON
SET XACT_ABORT ON


DECLARE @ErrorMessage varchar(1000)



BEGIN TRANSACTION


    --Insert to Valuation
    INSERT INTO [Valuation]
    (
        TrackingNumber,
        FormMobiValuationId,
        ValuationPropertyId, -- new
        ValuationFileName,
        Date,
        ValuationStatus,
        IsActive
    )
    VALUES
    (
        @TrackingNumber,
        @FormMobiValuationId,
        @ValuationPropertyId,--new
        @ValuationFileName,
        GETDATE(),
        1, --Created
        1
    )





IF @@ERROR > 0
BEGIN
    SET @ErrorMessage = 'Valuation Insert failed'
    GOTO ErrorHandler
END
ELSE
BEGIN
    COMMIT TRANSACTION
    RETURN
END



ErrorHandler:

RAISERROR(@ErrorMessage,16,1);
ROLLBACK TRANSACTION
RETURN -1

发生错误的 C# 调用,错误消息出现在最后一行。

 public ObjectResult<Valuation> ValuationCreate(global::System.String trackingNumber, global::System.String formMobiValuationId, Nullable<global::System.Int32> valuationPropertyId, global::System.String valuationFileName)
        {
            ObjectParameter trackingNumberParameter;
            if (trackingNumber != null)
            {
                trackingNumberParameter = new ObjectParameter("TrackingNumber", trackingNumber);
            }
            else
            {
                trackingNumberParameter = new ObjectParameter("TrackingNumber", typeof(global::System.String));
            }

            ObjectParameter formMobiValuationIdParameter;
            if (formMobiValuationId != null)
            {
                formMobiValuationIdParameter = new ObjectParameter("FormMobiValuationId", formMobiValuationId);
            }
            else
            {
                formMobiValuationIdParameter = new ObjectParameter("FormMobiValuationId", typeof(global::System.String));
            }

            ObjectParameter valuationPropertyIdParameter;
            if (valuationPropertyId.HasValue)
            {
                valuationPropertyIdParameter = new ObjectParameter("ValuationPropertyId", valuationPropertyId);
            }
            else
            {
                valuationPropertyIdParameter = new ObjectParameter("ValuationPropertyId", typeof(global::System.Int32));
            }

            ObjectParameter valuationFileNameParameter;
            if (valuationFileName != null)
            {
                valuationFileNameParameter = new ObjectParameter("ValuationFileName", valuationFileName);
            }
            else
            {
                valuationFileNameParameter = new ObjectParameter("ValuationFileName", typeof(global::System.String));
            }

            return base.ExecuteFunction<Valuation>("ValuationCreate", trackingNumberParameter, formMobiValuationIdParameter, valuationPropertyIdParameter, valuationFileNameParameter);
        }
4

13 回答 13

16

该消息意味着存储过程的结果不包含名为 的列ValudationId。仔细检查您的select语句并在 SSMS 中运行它,以确保您恢复了该列。

编辑:您的程序不包含select语句。您需要选择插入的标识值(scope_identity()例如使用函数),以便 EF 可以将其映射回实体。

例如,

insert into Table
(
    Col1,
    Col2
)
values
(
    1,
    2
)

select scope_identity() as IdentityColName

另外,顺便说一句,您的插入语句中不需要所有的交易业务;您只有一个正在修改数据的语句(您的插入)。

于 2013-01-09T13:02:24.737 回答
12

对于那些仍然遇到相同错误的人,请确保您指向/连接到正确的数据库。花了几个小时后,我发现我正在处理活动数据库而不是测试数据库。当然,我对测试数据库中的存储过程所做的更改在活动数据库中没有等效性。

于 2013-09-27T15:29:20.500 回答
10

在我的情况下,它返回数据,但未提供列名,由于CAST没有列名别名的语句,导致它变为空白。缺少列名错误最终导致 EF 生成报告的映射失败。

通过在 SSMS 中进行实际调用并查看结果,实际结果显示了这个现在明显的错误:

在此处输入图像描述

将 SQL 中的列命名为 EF 预期的内容可解决此问题。

于 2016-03-09T20:37:32.233 回答
4

Avinash,很好地调用 ExecuteSQLCommand 和“非查询”。但是,Pornster 指的是 ExecuteFunction 调用一个 SP 并返回结果。要解决此问题,请从您的 SP 中删除“return”语句,它将起作用。当您使用 return 语句时,SP 将返回一个 int 而不是您的 select 查询。

于 2014-05-19T04:34:31.770 回答
2

Strange, I solved this by adding the GO command to the end of by stored procedure.

于 2015-01-15T16:34:50.673 回答
2

我修复了这个问题的版本,通过在 VS 中浏览模型,在函数导入下找到存储过程并将函数的返回类型更改为无

于 2015-02-27T17:44:07.037 回答
2

如果您正在插入/删除/更新(这些被 EF 视为“非查询”),并且可以由我们的代码使用

context.Database.ExecuteSqlCommand(insert into Table (Col1,Col2) values (1,2));

但是,如果正在对原始 SQL 语句进行选择查询,则使用

context.DbSet<Table_name>.SqlQuery(select * from table_name).ToList();

或 context.Database.SqlQuery(select * from table_name).ToList();

EF 中的 SqlQuery() 函数,由于奇怪的原因,抛出异常插入/删除/更新操作。(抛出的异常是“类型的成员,在数据读取器中没有对应的同名列。”)但是如果您打开Sql Management Studio并检查条目,它实际上已经执行了操作。

于 2013-10-11T07:10:05.110 回答
1

重要的场景之一是通过不同的条件返回不同的结果。例如,当您使用 IF 命令时,可能会从每个分支返回不同的结果集。由于 EF 在导入 SP 时设置了返回集合,因此期望 [type one] 集合但获取 [type 2] 集合然后引发错误,在数据读取器中没有相应的列。因此,任何具有返回结果集的 SP 都必须从其上的每个部分返回相同的集合(作为列名和计数),如下所示:

IF (Condition 1)
BEGIN
  SELECT [column1], [column2], [column3], ... FROM [...]
END
ELSE
BEGIN
  SELECT [column1], [column2], [column3], ... FROM [...]
END

这在同一问题上对我有用,希望对我有所帮助。

更新:

另一次,当我在Function Imports. 真的,我没想到 Typed 或一些 Collection 值,也许只需要一个整数作为 Out 参数,但我忘了设置Returns a Collection OfNone. 因此,如果您不希望有任何返回结果,请转到您的模型并在Model Browser>Function Imports中右键单击 SP 有问题并单击编辑,然后检查该Returns a Collection Of部分并将其设置为None.

于 2014-12-25T22:54:27.003 回答
1

还要注意模型的 EDMX 文件将数据库列名称重新映射到与相应类对象不同的名称的情况。

就我而言,存储过程返回的列名称中包含空格[Monthly Bill Rate]。为了处理这个问题,列名在模型中被重新映射。

在某些时候,SP 返回列已重命名为[MonthlyBillRate],但模型未更新为对应。当我搜索代码时MonthlyBillRate,它在Designer.cs文件中为MonthlyBillRate. 我不明白为什么我得到了例外。经过仔细检查,我在 EDMX 中发现了重新映射的名称。

模型.edmx

重新映射通过属性发生在ScalarProperty标签中。ColumnName

 <FunctionImportMapping FunctionImportName="BillingReport" FunctionName="Model.Store.BillingReport">
  <ResultMapping>
    <ComplexTypeMapping TypeName="Model.BillData">
      <ScalarProperty Name="MonthlyBillRate" ColumnName="Monthly Bill Rate" />
    </ComplexTypeMapping>
  </ResultMapping>

模型设计器.cs

    [EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)]
    [DataMemberAttribute()]
    public Nullable<global::System.Decimal> MonthlyBillRate
    {
      ... etc ...
    }
于 2017-07-28T14:05:22.877 回答
1

就我而言,正如 Brett Jones 建议的那样,解决方案是从我的存储过程中删除“RETURN”语句,只留下“SELECT”部分。我花了好几个小时尝试在网上找到的各种解决方案,但就是这么简单。

于 2015-12-09T11:06:01.267 回答
0

当心存储过程末尾的“select *”!在那条黑暗的道路上只有废墟。

于 2019-11-20T01:15:00.703 回答
0

这不适用于这种特殊情况,但是我遇到了类似的问题,即引发了相同的错误,但指定的成员类型是我的选择中的一列,后缀为 1 ....这是由于我返回相同的在我的选择中列两次....示例:-

SELECT
    CustomerId,
    FirstName,
    LastName,
    CustomerId
FROM
    Customers
于 2016-08-10T11:15:04.073 回答
0

可能是您在使用 select 时没有给出列的别名。

于 2015-08-13T11:35:20.983 回答