J'ai la procédure définie par l'utilisateur suivante pour appeler une donnée calculée à partir de la base de données avec 2 paramètres pour renvoyer un entier (*))Exécutez la procédure stockée en utilisant Entity Framework Core 1.1 erreur "erreur": "La clé donnée n'était pas présente dans le dictionnaire"
USE [QIIS2]
GO
PROCEDURE [dbo].[sp.GetCansTotals]
@startdt datetime2,
@enddt datetime2,
@hospitalId int
AS
BEGIN
SET NOCOUNT ON;
SELECT COUNT(*) AS TotalCancelled
FROM Cans
WHERE (OperDt BETWEEN @startdt AND @enddt)
AND (hospitalId = @hospitalId);
END
le référentiel pour appeler la procédure:
public IEnumerable<Can> getcanstotal(int @hospitalId, string @startdt, string @enddt)
{
_context.Database.OpenConnection();
DbCommand cmd = _context.Database.GetDbConnection().CreateCommand();
cmd.CommandText = "GetCansTotals";
cmd.CommandType = CommandType.StoredProcedure;
IEnumerable<Can> can;
using (_context)
{
can = _context.LoadStoredProc("GetCansTotals")
.WithSqlParam("@hospitalId", @hospitalId)
.WithSqlParam("@startdt", @startdt)
.WithSqlParam("@enddt", @enddt)
.ExecuteStoredProc<Can>();
}
return can;
}
et le contrôleur:
[HttpGet("byParams")]
public IActionResult GetCanTotals(int hospitalId, string startdt, string enddt)
{
var cans = _unitOfWork.Cans.getcanstotal(hospitalId, startdt, enddt);
return Ok(Mapper.Map<IEnumerable<CanViewModel>>(cans));
}
Voici les EFExctensions.cs pour ExecStoredProced et Maping:
namespace DAL.Extensions
{
public static class EFExtensions
{
/// <summary>
/// Creates an initial DbCommand object based on a stored procedure name
/// </summary>
/// <param name="context"></param>
/// <param name="storedProcName"></param>
/// <returns></returns>
public static DbCommand LoadStoredProc(this DbContext context, string storedProcName)
{
var cmd = context.Database.GetDbConnection().CreateCommand();
cmd.CommandText = storedProcName;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
return cmd;
}
/// <summary>
/// Creates a DbParameter object and adds it to a DbCommand
/// </summary>
/// <param name="cmd"></param>
/// <param name="paramName"></param>
/// <param name="paramValue"></param>
/// <returns></returns>
public static DbCommand WithSqlParam(this DbCommand cmd, string paramName, object paramValue)
{
if (string.IsNullOrEmpty(cmd.CommandText) && cmd.CommandType != System.Data.CommandType.StoredProcedure)
throw new InvalidOperationException("Call LoadStoredProc before using this method");
var param = cmd.CreateParameter();
param.ParameterName = paramName;
param.Value = paramValue;
cmd.Parameters.Add(param);
return cmd;
}
/// <summary>
/// Executes a DbDataReader and returns a list of mapped column values to the properties of <typeparamref name="T"/>
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="command"></param>
/// <returns></returns>
public static IList<T> ExecuteStoredProc<T>(this DbCommand command)
{
using (command)
{
if (command.Connection.State == System.Data.ConnectionState.Closed)
command.Connection.Open();
try
{
using (var reader = command.ExecuteReader())
{
return reader.MapToList<T>();
}
}
finally
{
command.Connection.Close();
}
}
}
/// <summary>
/// Retrieves the column values from the stored procedure and maps them to <typeparamref name="T"/>'s properties
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="dr"></param>
/// <returns>IList<<typeparamref name="T"/>></returns>
private static IList<T> MapToList<T>(this DbDataReader dr)
{
var objList = new List<T>();
var props = typeof(T).GetRuntimeProperties();
var colMapping = dr.GetColumnSchema()
.Where(x => props.Any(y => y.Name.ToLower() == x.ColumnName.ToLower()))
.ToDictionary(key => key.ColumnName.ToLower());
if (dr.HasRows)
{
while (dr.Read())
{
T obj = Activator.CreateInstance<T>();
foreach (var prop in props)
{
var val = dr.GetValue(colMapping[prop.Name.ToLower()].ColumnOrdinal.Value);
prop.SetValue(obj, val == DBNull.Value ? null : val);
}
objList.Add(obj);
}
}
return objList;
}
}
}
Lors du passage de la demande avec postier:
http://localhost:56963/api/cansdatas/byParams?hospitalId=2&startdt=2016-01-01&enddt=2016-12-31
Erreur:
"error": "The given key was not present in the dictionary."
Quelqu'un pourrait-il aider ??
SOLVED juste de supprimer l'exécution procédure stockée et utilisée le code suivant:
public async Task<IEnumerable<Can>> Get()
{
return await appContext.Cans.FromSql("GetCansList").ToArrayAsync();
}
Vous nous montrez une procédure 'GetCanTotals' qui prend trois paramètres - mais la méthode que vous avez appelle' GetCansList' (une autre * procédure * stockée, semble-t-il) qui semble prendre ** aucun paramètre ** - vous ne pouvez donc pas fournir de paramètres à une procédure stockée ne vous attendez pas .... ou êtes-vous simplement en train d'appeler le ** mauvaise ** procédure stockée dans votre code C# ??? –
Vous avez raison, j'ai corrigé le nom de la procédure MAINTENANT j'obtiens l'erreur suivante "error": "Impossible de trouver la procédure stockée 'sp.GetCansTotals'." –
Votre procédure stockée est définie en tant que dbo.sp.GetCansTotals. Pour moi, cela se lit comme base de données = dbo, schéma = sp, procédure stockée = GetCansTotals. Pouvez-vous simplement le définir comme dbo.GetCansTotals et mettre à jour votre référence pour correspondre et voir si cela fonctionne? – natwallbank