1

Je travaille sur une application héritée et je suis en train de faire un appel à une procédure stockée qui retourne un entier mais je Je reçois une erreur de mappage. L'erreur lui-même est celle-ci:Obtenir paramètre de sortie de procédure stockée avec Entity Framework est de lancer une erreur de cartographie: Le lecteur de données est incompatible avec le spécifié

The data reader is incompatible with the specified IF_Insert_Incidents_Citizen'. A member of the type, 'intID', does not have a corresponding column in the data reader with the same name.

J'ai essayé de changer le nom de _intId, sachant que Entity Framework traduit tous les noms commençant par @variable à un _variable.

La chose étrange est que si je fais usage LINQPad et faire un appel à la procédure stockée je reçois la valeur correcte de @intID

enter image description here

enter image description here

Ceci est la procédure stockée:

CREATE PROCEDURE [dbo].[IF_Insert_Incidents_Citizen] 
    @chvFolio varchar(50), 
    @chvOwner_Name varchar(100), 
    @chvOwner_Address varchar(100), 
    @dtsDate_Created smalldatetime, 
    @intUser_ID integer, 
    @chvDescription varchar(250), 
    @chvEmail varchar(50), 
    @intIncident_Type_ID integer, 
    @intIncident_Status integer, 
    @intID int Output 
AS 
    SET nocount on 

    DECLARE @intErrorCode INT 
    DECLARE @intApp_ID INT 

    SELECT @intIncident_Type_ID = CAST(Param_Value AS INT) 
    FROM IF_Parameters 
    WHERE Param_Name = 'Citizen_Incident_Type_ID' 

    BEGIN 
     --Get an application id 
     INSERT INTO MasterApplication (DateCreated) 
     VALUES (getdate()) 

     SELECT @intApp_ID = SCOPE_IDENTITY() 

     INSERT INTO IF_Incidents 
     (
      Folio, 
      Owner_Name, 
      Owner_Address, 
      Date_Created, 
      User_ID, 
      Description, 
      Incident_Type_ID, 
      Incident_Status, 
      App_ID 
     ) 
     VALUES 
     (
      @chvFolio, 
      @chvOwner_Name, 
      @chvOwner_Address, 
      @dtsDate_Created, 
      @intUser_ID, 
      @chvDescription , 
      @intIncident_Type_ID, 
      @intIncident_Status, 
      @intApp_ID 
     ) 
     Select @intErrorCode = @@Error, @intID = SCOPE_IDENTITY() 

     --Insert Complaint 
     INSERT INTO IF_Complaints 
     (
      Incident_ID, 
      Complainant_ID, 
      Description , 
      User_ID, 
      Officer_Assigned_ID, 
      Complaint_Status_ID, 
      Date_Made, 
      Email_Complainant 
     ) 
     VALUES 
     (
      @intID, 
      Null, 
      @chvDescription + ' at ' + @chvOwner_Address, 
      1, 
      1, 
      1, 
      @dtsDate_Created , 
      @chvEmail 
     ) 
     Select @intErrorCode = @@Error--, @intID = SCOPE_IDENTITY() 
    End 

    Return @intErrorCode 

Comme vous pouvez le voir dans la procédure stockée, le IntID obtient toujours en valeur cremental après l'insertion, appelant SCOPE_IDENTITY()

Maintenant, je suis en train d'appeler ma procédure stockée en utilisant Entity Framework de la manière suivante:

var bptRep = DependencyFactory.GetDependency<ICetRepository<IF_Insert_Incidents_Citizen>>(); 
var parameters = GetIfInsertIncidentsCitizenParamenters(); 
var res = bptRep.GetAllFromStoredProcedure(storedProcedure, parameters); 

L'utilisation du référentiel de cette classe

//class with just the return value 
public class IF_Insert_Incidents_Citizen 
{ 
    public int? intID { get; set; } 
} 

Ici, je reçois tous les paramètres de la procédure stockée

private IEnumerable<SqlParameter> GetIfInsertIncidentsCitizenParamenters() 
{ 
     // Create Parameters 
     var parameters = new List<SqlParameter>(); 

     var param1 = CreateSqlParameter("@chvFolio", SqlDbType.NVarChar, ParameterDirection.Input, criteria["chvFolio"].Value, 50); 

     parameters.Add(param1); 

      .... 

     var paramX = CreateSqlParameter("@intIncident_Status", SqlDbType.Int, ParameterDirection.Input, 10); 
     parameters.Add(paramX); 

     var outparam = CreateSqlParameter("@intID", SqlDbType.Int, ParameterDirection.InputOutput, DBNull.Value); 
     parameters.Add(outparam); 
} 

public IQueryable<TEntity>GetAllFromStoredProcedure(string storedProcedure, IEnumerable<SqlParameter> parameters) 
{ 
    var result = Context.Database.SqlQuery<TEntity>(storedProcedure, parameters).AsQueryable();  
    return result; 
} 

J'ai suivi l'approche @GertArnold suggéré, mais ne fonctionne toujours pas, ce sont mes paramètres et le code

enter image description here

var returnCode = new SqlParameter("@ReturnCode", SqlDbType.Int); 
returnCode.Direction = ParameterDirection.Output; 

var sql = "exec IF_Insert_Incidents_Citizen @chvFolio, @chvOwner_Name, @chvOwner_Address, @dtsDate_Created, @intUser_ID, @chvDescription, @chvEmail, @intIncident_Type_ID, @intIncident_Status, @intID OUT"; 

var data = ctx.Database.SqlQuery<object>(sql, returnCode, parameters); 

var result = data.FirstOrDefault(); 
+1

Regardez [ce] (https: // stackoverflow .com/a/33263793/861716) –

+0

@GertArnold J'ai testé l'approche à partir de là, mais je me manque quelque chose, parce que ne parvient toujours pas. Je présente le OUT sur l'appel du storeprocedure et essaye celui qui fonctionne, je mets le ReturnCode aussi bien et ne fonctionne pas, je reçois d'autres erreurs – Heinrich

Répondre

1

Enfin @GertArnold me mettre sur la bonne voie, si vous avez lu ce après, s'il vous plaît le faire, vous permettra d'économiser beaucoup de temps Stored procedures with output parameters using SqlQuery in the DbContext API

Je viens d'ajouter à mon @intId OUT sur l'appel exec, il n'y a pas besoin de créer une variable ReturnCode et appelez exec @ReturnCode = ....

var returnCode = new SqlParameter("@ReturnCode", SqlDbType.Int); 
returnCode.Direction = ParameterDirection.Output; 

Mon code ressemble enfin comme celui-ci, s'il vous plaît être conscient à appeler la méthode .ToArray sur les paramètres au lieu de passer une collection de IEnumerable ou IList la méthode

var sql = "exec IF_Insert_Incidents_Citizen @chvFolio, @chvOwner_Name, @chvOwner_Address, @dtsDate_Created, @intUser_ID, @chvDescription, @chvEmail, @intIncident_Type_ID, @intIncident_Status, @intID OUT"; 

var data = ctx.Database.SqlQuery<object>(sql, returnCode, parameters.ToArray()); 

var result = data.FirstOrDefault();