web-dev-qa-db-ja.com

EFマップオブジェクトからの互換性のないデータリーダー例外

Entity Frameworkを使用しており、テーブルとそのストアドプロシージャを更新しましたが、ストアドプロシージャが呼び出されたときに次のエラーが表示されます。

データリーダーは、指定された 'FormValueModel.Valuation'と互換性がありません。タイプ「ValuationId」のメンバーには、データリーダーに同じ名前の対応する列がありません。

ValuationIdは、自動インクリメントしたい私の主なキーです。

SQL Management Studioからストアドプロシージャ検索を実行できます。アプリケーションを実行すると、データベースに書き込みますが、エラーメッセージが表示されます。

私はEntity Frameworkに精通しておらず、基本だけを知っています。それは、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);
        }
23
Pomster

このメッセージは、ストアドプロシージャの結果にValudationIdという名前の列が含まれていないことを意味します。 selectステートメントを再確認し、SSMSで実行して、その列を元に戻していることを確認します。

EDIT:プロシージャにselectステートメントが含まれていません。 EFがエンティティにマップし直すことができるように、挿入されたID値を選択する必要があります(たとえば、scope_identity()関数を使用)。

例えば、

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

select scope_identity() as IdentityColName

また、余談ですが、insertステートメントですべてのトランザクションビジネスが必要なわけではありません。データを変更している1つのステートメント(挿入)のみがあります。

14
Adam Robinson

まだ同じエラーが発生する場合は、正しいデータベースにポイント/接続していることを確認してください。何時間も過ごした後、私はテスト用のデータベースではなくアクティブなデータベースで作業していることがわかりました。そしてもちろん、テストデータベースのストアドプロシージャに加えた変更は、アクティブデータベースでは同等ではありませんでした。

12
usefulBee

私の場合、データを返していましたが、列がなかったCASTステートメントのために、列名が提供されていません名前エイリアス、blankになりました。列名の欠落エラーにより、EFによって報告されたマッピングエラーが生成されました。

SSMSで実際の呼び出しを行い、結果を表示することにより、その実際の結果は次の明らかな間違いを示しましたnow

enter image description here

SQLの列にEFが期待する名前を付けると、問題が修正されました。

8
ΩmegaMan

Avinash、ExecuteSQLCommandおよび 'non-query'の適切な呼び出し。ただし、PornsterはExecuteFunctionを参照してSPを呼び出し、結果を返します。この問題を解決するには、SPから 'return'ステートメントを削除しますそれが機能しますreturnステートメントを使用すると、SPは選択クエリではなくintを返します。

4
Brett Jones

奇妙なことに、ストアドプロシージャの最後に [〜#〜] go [〜#〜] コマンドを追加することでこれを解決しました。

2
FredL

この問題の私のバージョンを修正しました。VSでモデルを参照し、関数のインポートでストアドプロシージャを見つけ、関数の戻り値の型をNoneに変更しました

2
Flexicoder

挿入/削除/更新(これらは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を開いてエントリを確認すると、実際に操作が実行されます。

2

重要なシナリオの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のReturn Collection Typeが間違っていたときに、このエラーメッセージが表示されました。本当に私はTypedやいくつかのCollectionの値を期待していなかったので、Outパラメーターとして整数が必要なのかもしれませんが、Returns a Collection OfNoneに設定するのを忘れていました。返される結果が予想されない場合は、モデルに移動し、Model Browser> Function ImportsでSP has issues and Edit]をクリックしてから、 Returns a Collection Ofセクションで、Noneに設定します。

1
QMaster

私の場合、Brett Jonesが示唆したように、解決策はストアドプロシージャから "RETURN"ステートメントを削除するで、単に "SELECT"部分のみを残すことでした。私は何時間もかけてオンラインで見つけたあらゆる種類のソリューションを試してみましたが、それはそれと同じくらい簡単でした。

1
giagiu

また、モデルの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 ...
    }
0
Walter Stabosz

これはこの特定のケースには当てはまりませんが、同じエラーがスローされましたが、指定されたメンバータイプが1でポストフィックスされたselectの列であるという同様の問題がありました...これは同じを返すためでした私のselect .... exampleの列を2回

SELECT
    CustomerId,
    FirstName,
    LastName,
    CustomerId
FROM
    Customers
0
Wayne Feltham

列のエイリアス名を指定せずにselectを使用している可能性があります。

0