没有为CLR类型'Int32 []'

时间:2018-08-05 09:58:30

标签: c# entity-framework-core

当我从ASP.NET Core项目中的Entity Framework Core(v2.0)执行SQL Server存储过程时,出现此异常:

  

InvalidOperationException:找不到CLR类型'Int32 []'到关系类型的映射

SQL Server存储过程代码如下:

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;

ASP.NET Core数据模型如下:

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; }
}

ASP.net核心控制器代码以执行存储过程:

_context.Database.ExecuteSqlCommand("sp-UpdateProductOrderAndStock @p0, @p1", parameters: new[] { customerProductDelivery.CustomerOrderID,customerProductDelivery.DeliveryQty });

3 个答案:

答案 0 :(得分:11)

您正陷入典型的params object[]陷阱。

首先,让我们看看表达式的类型是什么

var parameters = new[] { customerProductDelivery.CustomerOrderID,customerProductDelivery.DeliveryQty }

由于两个元素的类型均为int,因此推断的类型为int[]

现在,有2个ExecuteSqlCommand方法重载,使您可以分别传递参数-一个重载params object[],第二个重载IEnumerable<object>

尽管IEnumerable<T>是协变的,但协变不适用于值类型,因此IEnumerable<int>不能被视为IEnumerable<object>,因此第二个重载不匹配。

因此,唯一有效的重载是接收params object[]的重载。但是由于无法将int[]强制转换为object[],因此编译器将其视为 object,发出类似new object[] { parameters }的内容。

下一个效果是EF方法接收int[]并生成有问题的异常。

话虽如此,它可以通过多种方式解决。

一种方法是从通话中删除new [] { },这是params object[]构造的全部思想:

_context.Database.ExecuteSqlCommand(
    "Update_ProductOrderAndStock @p0, @p1", customerProductDelivery.CustomerOrderID, customerProductDelivery.DeliveryQty);

另一种方法是将new []替换为显式new object[]

另一种方法是利用引入的String interpolation in FromSql and ExecuteSqlCommand EF核心:

_context.Database.ExecuteSqlCommand(
    $"Update_ProductOrderAndStock {customerProductDelivery.CustomerOrderID}, {customerProductDelivery.DeliveryQty}");

答案 1 :(得分:1)

请更新代码

来自

    _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());

答案 2 :(得分:0)

另一个答案

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