web-dev-qa-db-fra.com

Aucun mappage vers un type relationnel ne peut être trouvé pour le type CLR 'Int32 []'

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 });
6
Victor

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}");
8
Ivan Stoev

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());
1
Md. Abdul Alim

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); 
0
Victor