webentwicklung-frage-antwort-db.com.de

Inkompatible Datenleser-Ausnahme von EF zugeordneten Objekten

Ich verwende Entity Framework und habe eine Tabelle und ihre gespeicherte Prozedur aktualisiert. Ich erhalte jedoch die folgende Fehlermeldung, wenn die gespeicherte Prozedur aufgerufen wird.

Der Datenleser ist mit dem angegebenen .__ nicht kompatibel. 'FormValueModel.Valuation'. Ein Member des Typs 'ValuationId' tut dies Sie haben keine entsprechende Spalte im Datenleser mit demselben Namen.

ValuationId ist mein Hauptschlüssel, den ich automatisch erhöhen möchte.

Ich kann die gespeicherte Prozedur find aus dem SQL Management Studio ausführen. Wenn ich meine Anwendung ausführe, wird sie in die Datenbank geschrieben. Die Fehlermeldung wird jedoch angezeigt.

Ich bin mit Entity Framework nicht vertraut und habe nur die Grundlagen, und ich denke, es könnte ein Mapping-Problem aus dem model.edmx sein.

Was wäre die korrekte Prozedur, um die Tabellen und gespeicherten Prozeduren im Modell neu zu erstellen und abzubilden?


Gespeicherte Prozedur.

    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 # -Aufruf bei Auftreten eines Fehlers. Die Fehlermeldung wird in der letzten Zeile angezeigt.

 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);
        }
22
Pomster

Die Nachricht bedeutet, dass die Ergebnisse der gespeicherten Prozedur keine Spalte mit dem Namen ValudationId enthalten. Überprüfen Sie Ihre select-Anweisung und führen Sie sie in SSMS aus, um sicherzustellen, dass Sie diese Spalte zurückbringen.

EDIT: Ihre Prozedur enthält keine select-Anweisung. Sie müssen den eingefügten Identitätswert auswählen (z. B. mit der Funktion scope_identity()), damit EF ihn der Entität zuordnen kann.

Zum Beispiel,

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

select scope_identity() as IdentityColName

Daneben benötigen Sie nicht das gesamte Transaktionsgeschäft in Ihrer Einfügeanweisung. Sie haben nur eine Aussage (Ihre Einfügung), die Daten ändert.

14
Adam Robinson

Stellen Sie für diejenigen, die immer noch die gleiche Fehlermeldung erhalten, sicher, dass Sie auf die richtige Datenbank zeigen/eine Verbindung herstellen. Nach Stunden habe ich herausgefunden, dass ich an der aktiven Datenbank arbeitete und nicht an der Testdatenbank. Und natürlich hatten die Änderungen, die ich an der gespeicherten Prozedur in der Testdatenbank vorgenommen hatte, keine Gleichwertigkeit in der aktiven Datenbank. 

11
usefulBee

In meinem Fall wurden Daten zurückgegeben, aber der Spaltenname wurde nicht bereitgestellt, da eine CAST-Anweisung ohne Aliasnamen für die Spaltennamen leer wurde. Der Fehler des fehlenden Spaltennamens generierte den gemeldeten Zuordnungsfehler von EF. 

Durch einen tatsächlichen Aufruf in SSMS und das Anzeigen des Ergebnisses zeigte dieses tatsächliche Ergebnis diesen offensichtlichen Fehler now

 enter image description here

Benennen der Spalte in SQL nach dem von EF erwarteten Problem.

7
ΩmegaMan

Avinash, guter Aufruf von ExecuteSQLCommand und 'non-query'. Pornster verweist jedoch auf ExecuteFunction, um ein SP aufzurufen und Ergebnisse zurückzugeben. Um dieses Problem zu beheben, entfernen Sie die 'return'-Anweisung von Ihrem SP und von dort wird funktionieren ... Wenn Sie eine return-Anweisung verwenden, gibt der SP ein int und nicht Ihre select-Abfrage zurück.

4
Brett Jones

Seltsam, ich habe das Problem gelöst, indem ich den Befehl GO am Ende einer gespeicherten Prozedur anfügte. 

2
FredL

Ich habe meine Version dieses Problems behoben, indem ich das Modell in VS durchsucht habe, die gespeicherte Prozedur unter Funktionsimporte gefunden habe und den Rückgabetyp der Funktion in Keine geändert habe

2
Flexicoder

Wenn Sie Einfügen/Löschen/Aktualisieren (diese werden von EF als "Nicht-Abfrage" betrachtet), können Sie sie mit unserem Code aufrufen 

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

Wenn Sie jedoch eine Abfrage für eine unformatierte SQL-Anweisung auswählen, verwenden Sie

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

oder context.Database.SqlQuery (wählen Sie * aus Tabellenname aus) .ToList ();

Die SqlQuery () - Funktion löst in EF aus seltsamen Gründen die Ausnahme zum Einfügen/Löschen/Aktualisieren aus. (Die geworfene Ausnahme ist "Ein Mitglied des Typs, hat keine entsprechende Spalte im Datenleser mit demselben Namen.") Es wurde jedoch tatsächlich eine Operation ausgeführt, wenn Sie Ihr SQL Management Studio öffnen und nach den Einträgen suchen.

2

Eines der wichtigsten Szenarien besteht darin, dass unterschiedliche Bedingungen unterschiedliche Ergebnisse liefern. Wenn Sie beispielsweise IF Command verwenden, wird möglicherweise eine andere Ergebnismenge aus jedem Zweig zurückgegeben. Wenn EF beim Importieren von SP die zurückgegebene Auflistung festlegt, erwarten Sie eine Auflistung [Typ Eins], erhalten Sie jedoch eine Auflistung [Typ 2], und geben Sie dann einen Fehler aus. Der Datenleser enthält keine entsprechende Spalte. Daher muss jede SP mit zurückgegebener Ergebnismenge dieselbe Sammlung (als Spaltenname und Anzahl) von jedem Teil darauf zurückgeben. Siehe unten:

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

Das hat bei mir in der gleichen Ausgabe geklappt und hoffe hilfreich zu sein.

pdate:

Ein anderes Mal habe ich diese Fehlermeldung erhalten, als ich Function Imports Falsch eingegeben habe. Eigentlich habe ich keine Typed- oder Collection-Werte erwartet und brauche vielleicht nur eine Ganzzahl als Out-Parameter, aber ich habe vergessen, Returns a Collection Of Auf None zu setzen. Wenn Sie also keine Rückgabe erwarten, gehen Sie zu Ihrem Modell und klicken Sie in Model Browser> Function Imports Mit der rechten Maustaste auf SP hat Probleme und klicken Sie auf Bearbeiten, dann Überprüfen Sie den Abschnitt Returns a Collection Of und setzen Sie ihn auf None.

1
QMaster

In meinem Fall bestand die Lösung laut Brett Jones darin, die "RETURN" -Anweisung aus meiner gespeicherten Prozedur entfernen, wobei einfach nur der "SELECT" -Teil übrig bleibt. Ich verbringe Stunden damit, alle möglichen Lösungen auszuprobieren, die ich online gefunden habe, aber so einfach war das.

1
giagiu

Achten Sie auch auf Fälle, in denen die EDMX-Datei Ihres Modells den Namen der Datenbankspalte einem anderen Element als dem entsprechenden Klassenobjekt zuordnet. 

In meinem Fall gab die gespeicherte Prozedur Spalten mit Leerzeichen in den Namen [Monthly Bill Rate] zurück. Um damit umzugehen, wurde der Spaltenname im Modell neu zugeordnet. 

Zu einem bestimmten Zeitpunkt wurde die Rückgabespalte SP in [MonthlyBillRate] umbenannt, das Modell wurde jedoch nicht entsprechend aktualisiert. Als ich den Code nach MonthlyBillRate durchsuchte, war er in der Designer.cs-Datei als MonthlyBillRate enthalten. Ich konnte nicht verstehen, warum ich die Ausnahme bekam. Bei näherer Betrachtung habe ich den neu zugeordneten Namen im EDMX gefunden.

Model.edmx

Die Neuzuordnung erfolgt im Tag ScalarProperty über das Attribut 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

Dies gilt nicht für diesen speziellen Fall, aber ich hatte ein ähnliches Problem, bei dem derselbe Fehler ausgegeben wurde, aber der angegebene Elementtyp war eine Spalte in meinem postfixierten Wert mit 1 .... Dies war darauf zurückzuführen, dass ich dasselbe zurückgab Spalte zweimal in meinem select .... Beispiel: -

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

Möglicherweise verwenden Sie select, ohne den Aliasnamen für die Spalte anzugeben.

0