当我从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 });
答案 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);