没有为CLR类型'Int32 []'找到关系类型的映射

Vic*_*tor 9 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;
Run Code Online (Sandbox Code Playgroud)

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; }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Iva*_*oev 13

你陷入了一个典型的params object[]陷阱.

首先,让我们看一下表达式的类型

var parameters = new[] { customerProductDelivery.CustomerOrderID,customerProductDelivery.DeliveryQty }
Run Code Online (Sandbox Code Playgroud)

由于两个元素都是类型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);
Run Code Online (Sandbox Code Playgroud)

另一种是new []用显式替换new object[].

还有一个是在FromSql和ExecuteSqlCommand中使用EF Core引入的字符串插值:

_context.Database.ExecuteSqlCommand(
    $"Update_ProductOrderAndStock {customerProductDelivery.CustomerOrderID}, {customerProductDelivery.DeliveryQty}");
Run Code Online (Sandbox Code Playgroud)


Md.*_*lim 7

请更新代码

    _context.Database.ExecuteSqlCommand(
                   "sp_UpdateProductOrderAndStock @p0, @p1", parameters: 
                     new[] 
                     { 
                        customerProductDelivery.CustomerOrderID,customerProductDelivery.DeliveryQty
                      });
Run Code Online (Sandbox Code Playgroud)

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());
Run Code Online (Sandbox Code Playgroud)