2017-03-03 2 views
0

Zur Zeit arbeite ich an der Bereinigung einiger Code auf dem Back-End einer Anwendung, die ich für die Wartung unter Vertrag habe. Ich bin über eine Methode gestolpert, bei der ein Anruf über Oracle Data Reader an die DB erfolgt. Nach der Untersuchung des SQL erkannte ich, dass es nicht notwendig war, Oracle Data Reader zu öffnen, um zu sehen, wie sich das Objekt, das gerade geladen wurde, bereits im Kontext unseres Entity Framework befand. Ich habe den Code geändert, um stattdessen dem Entity Model zu folgen. Unten sind die Änderungen, die ich vorgenommen habe.Fehler von SQL-Abfrage

Originalcode

var POCs = new List<TBLPOC>(); 

Context.Database.Connection.Open(); 
var cmd = (OracleCommand)Context.Database.Connection.CreateCommand(); 
OracleDataReader reader; 
var SQL = string.Empty; 
if (IsAssociate == 0) 
    SQL = @"SELECT tblPOC.cntPOC,INITCAP(strLastName),INITCAP(strFirstName) 
      FROM tblPOC,tblParcelToPOC 
      WHERE tblParcelToPOC.cntPOC = tblPOC.cntPOC AND 
       tblParcelToPOC.cntAsOf = 0 AND 
       tblParcelToPOC.cntParcel = " + cntParcel + " ORDER BY INITCAP(strLastName)"; 
else 
    SQL = @"SELECT cntPOC,INITCAP(strLastName),INITCAP(strFirstName) 
      FROM tblPOC 
      WHERE tblPOC.cntPOC NOT IN (SELECT cntPOC 
             FROM tblParcelToPOC 
             WHERE cntParcel = " + cntParcel + @" 
              AND cntAsOf = 0) 
       AND tblPOC.ysnActive = 1 ORDER BY INITCAP(strLastName)"; 
cmd.CommandText = SQL; 
cmd.CommandType = CommandType.Text; 
using (reader = cmd.ExecuteReader()) 
{ 
    while (reader.Read()) 
    { 
     POCs.Add(new TBLPOC { CNTPOC = (decimal)reader[0], 
           STRLASTNAME = reader[1].ToString(), 
           STRFIRSTNAME = reader[2].ToString() }); 
    } 
} 
Context.Database.Connection.Close(); 
return POCs; 

Ersatzcode

var sql = string.Empty; 
if (IsAssociate == 0) 
    sql = string.Format(@"SELECT tblPOC.cntPOC,INITCAP(strLastName),INITCAP(strFirstName) 
          FROM tblPOC,tblParcelToPOC 
          WHERE tblParcelToPOC.cntPOC = tblPOC.cntPOC 
           AND tblParcelToPOC.cntAsOf = 0 
           AND tblParcelToPOC.cntParcel = {0} 
          ORDER BY INITCAP(strLastName)", 
          cntParcel); 
else 
    sql = string.Format(@"SELECT cntPOC,INITCAP(strLastName), INITCAP(strFirstName) 
          FROM tblPOC 
          WHERE tblPOC.cntPOC NOT IN (SELECT cntPOC 
                 FROM tblParcelToPOC 
                 WHERE cntParcel = {0} 
                 AND cntAsOf = 0) 
           AND tblPOC.ysnActive = 1 
          ORDER BY INITCAP(strLastName)", 
          cntParcel); 

return Context.Database.SqlQuery<TBLPOC>(sql, "0").ToList<TBLPOC>(); 

Das Problem, das ich jetzt habe, ist, wenn der Ersatzcode ausgeführt wird, ich die folgende Fehlermeldung erhalten:

Die Datenleser ist mit dem angegebenen 'TBLPOC' nicht kompatibel. Ein Mitglied des Typs 'CNTPOCORGANIZATION' hat keine entsprechende Spalte im Datenleser mit demselben Namen.

Das Feld cntPOCOrganization existiert sowohl innerhalb von tblPOC als auch innerhalb der TBLPOC-Entität. cntPOCOrganization ist eine nullwertfähige Dezimalzahl (fragen Sie nicht, warum dezimal, ich selbst verstehe nicht, warum die früheren Kontraktoren Dezimal- gegen Ints für Identifikatoren verwendet haben ...). In dem früheren Code und dem neueren Code ist es jedoch nicht erforderlich, dieses Feld zu füllen. Ich bin verwirrt darüber, warum es in diesem speziellen Bereich Fehler gibt.

Wenn jemand einen Einblick hat, würde ich es wirklich zu schätzen wissen. Vielen Dank.

EDIT: Also nachdem ich darüber nachgedacht habe und ein wenig recherchiert habe, denke ich, ich weiß was das Problem ist. Im Entitätsmodell für TBLPOC ist das Feld cntPOCOrganization null, es ist jedoch ein Objekt an dieses Entitätsmodell gebunden, das als TBLPOCORGANIZATION bezeichnet wird. Ich überlege, ob es versucht, es zu füllen. Es hat auch cntPOCOrganization in sich und ich vermute, dass es vielleicht versucht, sich selbst zu füllen und ist, was das Problem verursacht.

Das ist vielleicht der Grund, warum der vorherige Auftragnehmer das Oracle Command geschrieben hat oder es durch das Entity Framework laufen ließ. Ich werde mich vorläufig zurückziehen (zu einem Stichtag und wirklich nicht zu lange damit spielen wollen). Vielen Dank!

+0

Es klingt für mich wie der Leser hat nicht alle Felder, die das Framework benötigt, um die Objekte auszufüllen. – JuanR

+0

Wie ich bereits erwähnt habe, denke ich, das Problem sind die Entitäten, die mit dieser Entität verbunden sind. Der Leser notiert sie und da in den Child-Objekten Non-Nullen vorhanden sind, wird ein Fehler ausgelöst. Es könnte auch sein, dass das Objekt fast alle seiner Felder auch aufgrund der Abfrage nicht enthält (die Abfrage zieht nur drei Felder, wenn es in Wirklichkeit mehr wie 10-15 Felder insgesamt gibt). – IyaTaisho

+0

Ja, ich denke du bist auf dem richtigen Weg. Sie bitten EF, die Ergebnisse der Abfrage für Sie zuzuordnen, damit erwartet wird, dass der Leser alles hat. Ich bin neugierig, ist das Feld "cntPOCOrganization" ein Objekt oder eine Menge? Es ist ein Objekt, dann muss es eine 1 zu 1 Beziehung in der Datenbank sein. – JuanR

Antwort

0

Dieser Fehler wird ausgegeben, wenn das EF-Entitätsmodell nicht mit dem Abfrageergebnis übereinstimmt. Wenn Sie Ihr Entitätsmodell, das Sie versuchen, dieses Objekt abzurufen, veröffentlichen, kann das SQL-Problem behoben werden. Im Allgemeinen müssen Sie verwenden:

+0

Ich habe die Namen korrigiert, nachdem ich gepostet habe, weil ich das gleiche dachte. Allerdings bekomme ich immer noch den gleichen Fehler. – IyaTaisho