我正在使用Entity Framework并更新了一个表及其存储过程,但是在调用存储过程时出现以下错误。
数据阅读器与指定的内容不兼容 '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);
}
答案 0 :(得分:14)
该消息表示存储过程的结果不包含名为ValudationId
的列。仔细检查您的select
声明并在SSMS中运行它,以确保您带回该列。
编辑:您的程序不包含select
声明。您需要选择插入的标识值(例如,使用scope_identity()
函数),以便EF可以将其映射回实体。
例如,
insert into Table
(
Col1,
Col2
)
values
(
1,
2
)
select scope_identity() as IdentityColName
另外,另外,您不需要在insert语句中使用所有事务业务;你只有一个声明(你的插入)正在修改数据。
答案 1 :(得分:11)
对于仍然遇到相同错误的用户,请确保指向/连接到正确的数据库。花了好几个小时后,我发现我正在处理活动数据库,而不是测试数据库。当然,我对测试数据库中的存储过程所做的更改在活动数据库中没有等效性。
答案 2 :(得分:8)
在我的情况下,它返回了数据,但由于没有列名别名的CAST
语句,列名称未提供导致它变为空白。丢失的列名称错误最终导致EF报告的映射失败。
通过在SSMS中进行实际调用并查看结果,实际结果显示此现在明显错误:
将SQL中的列命名为EF预期修复问题的内容。
答案 3 :(得分:4)
Avinash,对ExecuteSQLCommand和&#39;非查询&#39;的良好调用。但是,Pornster指的是ExecuteFunction来调用SP并返回结果。 要解决此问题,请删除&#39; return&#39;您SP的声明,它会起作用。 当您使用return语句时,SP将返回一个int而不是您的select查询。
答案 4 :(得分:2)
如果您要插入/删除/更新(这些被EF视为“非查询”),并且我们的代码可以使用
调用context.Database.ExecuteSqlCommand(insert into Table (Col1,Col2) values (1,2));
但是如果正在对原始SQL语句执行select查询,则使用
context.DbSet<Table_name>.SqlQuery(select * from table_name).ToList();
或context.Database.SqlQuery(select * from table_name).ToList();
SqlQuery()函数,在EF中,出于奇怪的原因,抛出异常插入/删除/更新操作。 (引发的异常是“类型的成员,数据读取器中没有相应的列具有相同的名称。”)但是,如果您打开Sql Management Studio并检查条目,它实际上已执行了操作。
答案 5 :(得分:2)
奇怪,我通过将GO命令添加到存储过程的末尾来解决了这个问题。
答案 6 :(得分:2)
通过在VS中浏览Model,在Function Imports下找到Stored Proc并将函数的返回类型更改为None
,我修复了我的问题版本答案 7 :(得分:1)
其中一个重要方案是根据不同条件返回不同的结果。例如,当您使用IF命令时,可能会从每个分支返回不同的结果集。由于EF在导入SP时设置了返回集合,因此期望[类型1]集合但获取[类型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 Parameter但我忘了将Returns a Collection Of
设置为None
。因此,如果您不希望任何退货结果,请转到您的模型并Model Browser
&gt; Function Imports
右键单击SP有问题,然后点击修改,然后查看Returns a Collection Of
部分并将其设置为None
。
答案 8 :(得分:1)
就我而言,正如Brett Jones所说,解决方法是从我的存储过程中删除“RETURN”语句,只留下“SELECT”部分。我花了几个小时尝试在网上找到的各种解决方案,但这很简单。
答案 9 :(得分:0)
您可能正在使用select而不为列提供别名。
答案 10 :(得分:0)
这不适用于这种特殊情况,但我有一个类似的问题,其中抛出相同的错误,但指定的成员类型是我的选择后固定的列.... 1这是由于我在我的select ....示例中返回相同的列两次: -
SELECT
CustomerId,
FirstName,
LastName,
CustomerId
FROM
Customers
答案 11 :(得分:0)
还要注意模型的EDMX文件将数据库列名重新映射到与相应类对象不同的实例。
在我的例子中,存储过程返回名称为[Monthly Bill Rate]
的空格的列。为了处理这个问题,列名在模型中重新映射。
在某些时候,SP返回列已重命名为[MonthlyBillRate]
,但模型未更新为对应。当我搜索MonthlyBillRate
的代码时,它在Designer.cs
文件中显示为MonthlyBillRate
。我无法理解为什么我会得到例外。经过仔细检查,我在EDMX中找到了重新映射的名称。
重新映射通过ScalarProperty
属性在ColumnName
标记中进行。
<FunctionImportMapping FunctionImportName="BillingReport" FunctionName="Model.Store.BillingReport">
<ResultMapping>
<ComplexTypeMapping TypeName="Model.BillData">
<ScalarProperty Name="MonthlyBillRate" ColumnName="Monthly Bill Rate" />
</ComplexTypeMapping>
</ResultMapping>
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)]
[DataMemberAttribute()]
public Nullable<global::System.Decimal> MonthlyBillRate
{
... etc ...
}
答案 12 :(得分:0)
请注意存储过程末尾的“选择*”!那条黑暗的道路上只有一片废墟。