Несовместимое исключение для чтения данных из сопоставленных объектов EF
Я использую работу с фреймом сущности и обновил таблицу и ее хранимую процедуру, но получаю следующую ошибку при вызове хранимой процедуры.
Считыватель данных несовместим с указанным "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);
}
12 ответов
Сообщение означает, что результаты хранимой процедуры не содержат столбец с именем ValudationId
, Дважды проверьте ваш select
и запустите его в SSMS, чтобы убедиться, что вы возвращаете этот столбец.
РЕДАКТИРОВАТЬ: Ваша процедура не содержит select
заявление. Вам нужно выбрать вставленное значение идентичности (используя scope_identity()
например), чтобы EF мог сопоставить его с сущностью.
Например,
insert into Table
(
Col1,
Col2
)
values
(
1,
2
)
select scope_identity() as IdentityColName
Кроме того, кроме того, вам не нужен весь этот бизнес транзакций в вашем операторе вставки; у вас есть только один оператор (ваша вставка), который изменяет данные.
Для тех, кто все еще получает ту же ошибку, убедитесь, что вы указываете / подключены к правильной базе данных. Потратив часы, я обнаружил, что работаю с активной базой данных, а не с тестовой. И, конечно, изменения, которые я внес в хранимую процедуру в тестовой базе данных, не имели эквивалента в активной базе данных.
В моем случае он возвращал данные, но имя столбца, не предоставленное, из-за CAST
оператор, который не имеет псевдонима столбца, стал пустым. Ошибка имени отсутствующего столбца закончилась генерацией сообщения об ошибке сопоставления EF.
Сделав реальный вызов в SSMS и просмотрев результат, этот реальный результат показал эту очевидную ошибку:
Присвоение имени столбцу в SQL того, что ожидал EF, решило проблему.
Avinash, хороший вызов на ExecuteSQLCommand и "не-запрос". Тем не менее, Pornster ссылается на ExecuteFunction, чтобы вызвать SP и вернуть результаты. Чтобы решить эту проблему, удалите оператор возврата из вашего SP, и он будет работать. Когда вы используете оператор return, SP будет возвращать int, а не ваш запрос select.
Странно, я решил это, добавив команду GO в конец хранимой процедуры.
Я исправил свою версию этой проблемы, просматривая Модель в VS, находя Сохраненный Процесс в разделе Импорт функций и меняя тип возвращаемого значения функции на Нет
Если вы вставляете / удаляете / обновляете (они рассматриваются EF как "незапрашиваемые") и могут быть вызваны нашим кодом с помощью
context.Database.ExecuteSqlCommand(insert into Table (Col1,Col2) values (1,2));
Но если вы делаете запрос select для необработанного оператора SQL, используйте
context.DbSet<Table_name>.SqlQuery(select * from table_name).ToList();
или context.Database.SqlQuery(выберите * из имени таблицы).ToList();
Функция SqlQuery() в EF по странным причинам вызывает исключение операции вставки / удаления / обновления. (Выдается исключение "Член типа, у которого нет соответствующего столбца в считывателе данных с тем же именем.") Но он фактически выполнил операцию, если вы откроете свою Sql Management Studio и проверите записи.
Также следите за случаями, когда файл EDMX вашей модели сопоставляет имя столбца базы данных с чем-то отличным от соответствующего объекта класса.
В моем случае хранимая процедура возвращала столбцы с пробелами в именах [Monthly Bill Rate]
, Чтобы справиться с этим, имя столбца было переназначено в модели.
В какой-то момент столбец возврата SP был переименован в [MonthlyBillRate]
, но модель не была обновлена, чтобы соответствовать. Когда я искал код для MonthlyBillRate
там это было в Designer.cs
подать как MonthlyBillRate
, Я не мог понять, почему я получил исключение. При ближайшем рассмотрении я нашел переназначенное имя в EDMX.
Model.edmx
Перераспределение происходит в ScalarProperty
тег через ColumnName
приписывать.
<FunctionImportMapping FunctionImportName="BillingReport" FunctionName="Model.Store.BillingReport">
<ResultMapping>
<ComplexTypeMapping TypeName="Model.BillData">
<ScalarProperty Name="MonthlyBillRate" ColumnName="Monthly Bill Rate" />
</ComplexTypeMapping>
</ResultMapping>
Model.Designer.cs
[EdmScalarPropertyAttribute(EntityKeyProperty=false, IsNullable=true)]
[DataMemberAttribute()]
public Nullable<global::System.Decimal> MonthlyBillRate
{
... etc ...
}
В моем случае, как предположил Бретт Джонс, решение состояло в том, чтобы удалить инструкцию "RETURN" из моей хранимой процедуры, оставив только часть "SELECT". Я часами пробую всевозможные решения, которые я нашел в Интернете, но это было так просто.
Одним из важных сценариев является получение разных результатов при разных условиях. Например, когда вы используете 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
, На самом деле я не ожидал типизированных или некоторых значений коллекции и, возможно, мне просто нужно целое число как выходной параметр, но я забыл установить Returns a Collection Of
в None
, Так что, если вы не ожидаете какого-либо результата возврата, перейдите к вашей модели и в Model Browser
> Function Imports
сделать правый клик на SP есть проблемы и нажать Edit, затем проверить Returns a Collection Of
раздел и установите его None
,
Это не применимо к данному конкретному случаю, но у меня была похожая проблема, в которой была выдана та же ошибка, но указанный тип элемента был столбцом в моем выбранном столбце, исправленном с 1.... это из-за того, что я возвращал то же самое столбец дважды в моем выборе.... пример:-
SELECT
CustomerId,
FirstName,
LastName,
CustomerId
FROM
Customers
ОСТЕРЕГАЙТЕСЬ "select *" в конце ваших хранимых процедур! Только руины лежат на этом темном пути.
Может быть, вы используете select без указания псевдонима столбца.