Подтвердить что ты не робот

Исключение несовместимого чтения данных из объектов, привязанных к 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

Вызов С#, где происходит ошибка, В последней строке появляется сообщение об ошибке.

 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);
        }
4b9b3361

Ответ 1

Сообщение означает, что результаты хранимой процедуры не содержат столбца с именем ValudationId. Дважды проверьте оператор select и запустите его в SSMS, чтобы убедиться, что вы возвращаете этот столбец.

РЕДАКТИРОВАТЬ: Ваша процедура не содержит оператора select. Вам нужно выбрать вставленное значение идентификатора (например, с помощью функции scope_identity()), чтобы EF мог отобразить его обратно в объект.

Например,

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

select scope_identity() as IdentityColName

Кроме того, в стороне вам не нужен весь этот транзакционный бизнес в вашей инструкции insert; у вас есть только один оператор (ваша вставка), который изменяет данные.

Ответ 2

Для тех, кто по-прежнему получает ту же ошибку, убедитесь, что вы указываете/подключаетесь к правильной базе данных. Проведя часы, я узнал, что работаю над активной базой данных, а не тестирующей. И, конечно, изменения, которые я внес в хранимую процедуру в базе данных тестирования, не имеют эквивалентности в активной базе данных.

Ответ 3

В моем случае он возвращал данные, но имя столбца, не предоставленное, из-за оператора CAST заставило его стать пустым. Ошибка имени отсутствующего столбца закончилась тем, что генерировала сообщение об ошибке отображения с помощью EF.

Выполняя фактический вызов в SSMS и просматривая результат, в результате появилась эта очевидная ошибка, как показано:

введите описание изображения здесь

Именование столбца в SQL, к которому EF ожидал исправления проблемы.

Ответ 4

Avinash, хороший вызов ExecuteSQLCommand и "не-запрос". Однако Pornster ссылается на ExecuteFunction для вызова SP и возврата результатов. Чтобы решить эту проблему, удалите оператор 'return' из вашего SP, и он будет работать. Когда вы используете оператор return, SP возвращает int, а не ваш запрос select.

Ответ 5

Если вы вставляете/удаляете/обновляете (они рассматриваются 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(выберите * from table_name).ToList();

Функция SqlQuery() в EF по странным причинам бросает исключение. Вставка/удаление/обновление. (Исключение выбрано "Член типа, не имеет соответствующего столбца в считывателе данных с тем же именем".) Но он фактически выполнил операцию, если вы открыли свою Sql Management Studio и проверили записи.

Ответ 6

Странно, я решил это, добавив команду GO в конец хранимой процедуры.

Ответ 7

Я исправил свою версию этой проблемы, просмотрев модель в VS, найдя хранимую программу в разделе "Импорт объектов" и изменив тип возврата функции на "Нет"

Ответ 8

Одним из важных сценариев является возвращение разных результатов по различным условиям. Например, когда вы используете IF Command, можете возвращать разные результирующие значения из каждой ветки. Поскольку 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

Это работает для меня в одной и той же проблеме, и надеюсь, будет полезно.

Update:

В другой раз я получил это сообщение об ошибке, когда у меня был неправильный тип возврата в Function Imports. На самом деле я не ожидал значений Typed или some Collection и, возможно, просто нуждался в целых числах как Out Parameter, но я забыл установить Returns a Collection Of в None. Поэтому, если вы не ожидаете, что какой-либо результат возврата вернется к вашей модели и в Model Browser > Function Imports, щелкните правой кнопкой мыши по SP, и нажмите "Изменить", затем проверьте раздел Returns a Collection Of и установите его на None.

Ответ 9

В моем случае, как предположил Бретт Джонс, решение было удалить оператор "RETURN" из моей хранимой процедуры, оставив только часть "SELECT". Я трачу часы и часы, пытаясь найти все виды решений, которые я нашел в Интернете, но это было так просто.

Ответ 10

Возможно, вы используете select, не указав псевдоним для столбца.

Ответ 11

Это не относится к этому конкретному случаю, но у меня была аналогичная проблема, в которой была сброшена одна и та же ошибка, но указанный тип элемента был столбцом в моем выделенном post-fixed с 1.... это было из-за меня возвращая тот же самый столбец дважды в мой выбор... Пример: -

SELECT
    CustomerId,
    FirstName,
    LastName,
    CustomerId
FROM
    Customers

Ответ 12

Также обратите внимание на случаи, когда ваш файл модели 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 ...
    }