Lorsque j'exécute une procédure stockée SQL Server à partir de Entity Framework Core (v2.0) dans mon projet ASP.NET Core, j'obtiens cette exception:
InvalidOperationException: aucun mappage vers un type relationnel ne peut être trouvé pour le type CLR 'Int32 []'
Le code de procédure stockée SQL Server ressemble à ceci:
CREATE PROCEDURE [dbo].[sp-UpdateProductOrderAndStock]
@customerOrderID INT,
@qty INT
AS
DECLARE @customerProductID INT
SET @customerProductID = (SELECT CustomerProductID
FROM dbo.CustomerOrder
WHERE ID = @customerOrderID)
SET NOCOUNT ON;
UPDATE dbo.CustomerOrder
SET CompletedQty = CompletedQty + @qty
WHERE ID = @customerOrderID;
UPDATE dbo.CProductStation
SET Qty = Qty - @qty
WHERE CustomerProductID = @customerProductID AND StationNo = 0;
Modèle de données ASP.NET Core comme ci-dessous:
public class CustomerProductDelivery
{
public int ID { get; set; }
public int CustomerOrderID { get; set; }
public DateTime DeliveryDate { get; set; }
public string DeliveryNo { get; set; }
public int DeliveryQty { get; set; }
public CustomerOrder CustomerOrder { get; set; }
}
Code de contrôleur principal ASP.net pour exécuter la procédure stockée:
_context.Database.ExecuteSqlCommand("sp-UpdateProductOrderAndStock @p0, @p1", parameters: new[] { customerProductDelivery.CustomerOrderID,customerProductDelivery.DeliveryQty });
Vous tombez dans un piège params object[]
typique.
Tout d'abord, voyons quel est le type de l'expression
var parameters = new[] { customerProductDelivery.CustomerOrderID,customerProductDelivery.DeliveryQty }
Comme les deux éléments sont de type int
, le type inféré est int[]
.
À présent, il existe 2 surcharges de méthode ExecuteSqlCommand
qui vous permettent de transmettre des paramètres séparément - un récepteur params object[]
et un second récepteur IEnumerable<object>
.
Bien que IEnumerable<T>
soit covariant, la covariance ne fonctionne pas pour les types valeur, donc IEnumerable<int>
ne peut pas être traité en tant que IEnumerable<object>
; par conséquent, la seconde surcharge ne correspond pas.
Donc, la seule surcharge valide est celle qui reçoit params object[]
. Mais comme int[]
ne peut pas être converti en object[]
, le compilateur le traite comme singleobject
, ce qui émet quelque chose comme new object[] { parameters }
.
L'effet suivant est que la méthode EF reçoit int[]
et génère l'exception en question.
Cela dit, il pourrait être réglé de plusieurs façons.
L’une consiste à supprimer new [] { }
de l’appel, qui est l’idée même de la construction params object[]
:
_context.Database.ExecuteSqlCommand(
"Update_ProductOrderAndStock @p0, @p1", customerProductDelivery.CustomerOrderID, customerProductDelivery.DeliveryQty);
Une autre consiste à remplacer le new []
par le new object[]
explicite.
Encore une autre consiste à utiliser le noyau EF introduit Interpolation de chaînes dans FromSql et ExecuteSqlCommand :
_context.Database.ExecuteSqlCommand(
$"Update_ProductOrderAndStock {customerProductDelivery.CustomerOrderID}, {customerProductDelivery.DeliveryQty}");
Veuillez mettre à jour le code
de
_context.Database.ExecuteSqlCommand(
"sp_UpdateProductOrderAndStock @p0, @p1", parameters:
new[]
{
customerProductDelivery.CustomerOrderID,customerProductDelivery.DeliveryQty
});
à
List<SqlParameter> pc = new List<SqlParameter>
{
new SqlParameter("@customerOrderID", customerProductDelivery.CustomerOrderI),
new SqlParameter("@qty", customerProductDelivery.DeliveryQty)
}
_context.Database.ExecuteSqlCommand("sp_UpdateProductOrderAndStock @customerOrderID, @qty", pc.ToArray());
Une autre réponse
var p0 = new SqlParameter("@customerOrderID", customerProductDelivery.CustomerOrderID);
var p1 = new SqlParameter("@qty", customerProductDelivery.DeliveryQty);
_context.Database.ExecuteSqlCommand("sp_UpdateProductOrderAndStock @customerOrderID, @qty", p0, p1);
//or var p0 = new SqlParameter("@p0", customerProductDelivery.CustomerOrderID);
//or var p1 = new SqlParameter("@p1", customerProductDelivery.DeliveryQty);
// or _context.Database.ExecuteSqlCommand("sp_UpdateProductOrderAndStock @p0, @p1", p0, p1);