C# 无法使用EF Core使用命名参数和输出参数执行SQL Server SP
尝试使用实体框架核心从SQL Server执行存储过程时遇到问题。此SP用于通过Econnect将外部数据与客户端ERP(Microsoft Dynamics Great Plains)集成 这是SP元数据(由于正文限制,我仅包括SP DDL行): 这是我试图用来运行SP的代码:C# 无法使用EF Core使用命名参数和输出参数执行SQL Server SP,c#,sql-server,linq,.net-core,entity-framework-core,C#,Sql Server,Linq,.net Core,Entity Framework Core,尝试使用实体框架核心从SQL Server执行存储过程时遇到问题。此SP用于通过Econnect将外部数据与客户端ERP(Microsoft Dynamics Great Plains)集成 这是SP元数据(由于正文限制,我仅包括SP DDL行): 这是我试图用来运行SP的代码: private EconnectSpExecutionResult MakeGpTransferBetweenBins(ColonyFuelTransferDto colonyFuelTransferD
private EconnectSpExecutionResult MakeGpTransferBetweenBins(ColonyFuelTransferDto colonyFuelTransferDb)
{
var spExecutionResult = new EconnectSpExecutionResult();
var spExecQuery = "EXECUTE [dbo].[taIVMultibinBinToBinTransfer] " +
"@I_vITEMNMBR" +
", @I_vLOCNCODE" +
", @I_vUOFM" +
", @I_vBIN" +
", @I_vQUANTITY" +
", @I_vTOBIN" +
", @O_iErrorState OUTPUT" +
", @oErrString OUTPUT";
var fuelItemIdParam = new SqlParameter("@I_vITEMNMBR", colonyFuelTransferDb.FuelItemId);
var locationGpIdParam = new SqlParameter("@I_vLOCNCODE", colonyFuelTransferDb.LocationGpId);
var measureUnitIdParam = new SqlParameter("@I_vUOFM", colonyFuelTransferDb.MeasureUnitId);
var sourceBinIdParam = new SqlParameter("@I_vBIN", colonyFuelTransferDb.SourceBinId);
var quantityParam = new SqlParameter("@I_vQUANTITY", colonyFuelTransferDb.Quantity);
var destinationBinIdParam = new SqlParameter("@I_vTOBIN", colonyFuelTransferDb.DestinationBinId);
var errorNumberParam = new SqlParameter("@O_iErrorState", spExecutionResult.ErrorNumber) { Direction = System.Data.ParameterDirection.Output };
var errorDescriptionParam = new SqlParameter("@oErrString", spExecutionResult.ErrorDescription) { Direction = System.Data.ParameterDirection.Output, Size = 255 };
_seaboardGpDbContext
.Database
.ExecuteSqlCommand
(
spExecQuery,
fuelItemIdParam,
locationGpIdParam,
measureUnitIdParam,
sourceBinIdParam,
quantityParam,
destinationBinIdParam,
errorNumberParam,
errorDescriptionParam
);
return spExecutionResult;
}
问题是我不能让它工作。SP有几个我想要避免的参数,让它们采用元数据中指定的默认值。此外,这个SP有两个输出参数,我需要在执行后检索它们,它们为您提供有关集成过程中可能发生的错误的信息
我得到的当前错误如下:将数据类型nvarchar转换为smallint时出错。。从实际运行的查询中可以看出,EF Core似乎没有使用命名参数:
declare @p9 int
set @p9=NULL
declare @p10 nvarchar(255)
set @p10=NULL
exec sp_executesql N'EXECUTE [dbo].[taIVMultibinBinToBinTransfer] @I_vITEMNMBR, @I_vLOCNCODE, @I_vUOFM, @I_vBIN, @I_vQUANTITY, @I_vTOBIN, @O_iErrorState OUTPUT, @oErrString OUTPUT',N'@I_vITEMNMBR nvarchar(9),@I_vLOCNCODE nvarchar(3),@I_vUOFM nvarchar(2),@I_vBIN nvarchar(3),@I_vQUANTITY decimal(6,2),@I_vTOBIN nvarchar(3),@O_iErrorState int output,@oErrString nvarchar(255) output',@I_vITEMNMBR=N'092001122',@I_vLOCNCODE=N'CZE',@I_vUOFM=N'LT',@I_vBIN=N'CZE',@I_vQUANTITY=1007.00,@I_vTOBIN=N'CHZ',@O_iErrorState=@p9 output,@oErrString=@p10 output
select @p9, @p10
如果您能给我任何指导或帮助,我将不胜感激。我尝试过几种选择,但都不奏效。在执行SP之前,我总是会遇到与实体框架核心或sql server引擎相关的异常
谢谢。问题在于参数将按照接收顺序提供给sp。您希望使用sp中的名称将它们分配给sp,这些名称可以相同 执行的sql基本上如下所示:
declare @I_vITEMNMBR char(30) = .. ,
@I_vLOCNCODE char(10) = ..,
@I_vUOFM char(8) = ..,
@I_vBIN char(15) = ..,
@I_vQUANTITY numeric(19, 5) = ..,
@I_vTOBIN char(15) = ..,
@O_iErrorState int,
@oErrString varchar(255)
EXECUTE [dbo].[taIVMultibinBinToBinTransfer]
@I_vITEMNMBR
, @I_vLOCNCODE
, @I_vUOFM
, @I_vBIN
, @I_vQUANTITY
, @I_vTOBIN
, @O_iErrorState OUTPUT
, @oErrString OUTPUT
@正在将I_vUOFM分配给@I_vQTYTYPE,这是错误的类型
你想要的是:
declare @I_vITEMNMBR char(30) = ..,
@I_vLOCNCODE char(10) = ..,
@I_vUOFM char(8) = ..,
@I_vBIN char(15) = ..,
@I_vQUANTITY numeric(19, 5) = ..,
@I_vTOBIN char(15) = ..,
@O_iErrorState int = ..,
@oErrString varchar(255) = ..
EXECUTE [dbo].[taIVMultibinBinToBinTransfer]
@I_vITEMNMBR = @I_vITEMNMBR
, @I_vLOCNCODE = @I_vLOCNCODE
, @I_vUOFM = @I_vUOFM
, @I_vBIN = @I_vBIN
, @I_vQUANTITY = @I_vQUANTITY
, @I_vTOBIN = @I_vTOBIN
, @O_iErrorState = @O_iErrorState OUTPUT
, @oErrString = @oErrString OUTPUT
是的,如果您只想提供这些参数,则必须将代码更改为以下内容:
var spExecQuery = @"EXECUTE [dbo].[taIVMultibinBinToBinTransfer]
@I_vITEMNMBR = @I_vITEMNMBR
, @I_vLOCNCODE = @I_vLOCNCODE
, @I_vUOFM = @I_vUOFM
, @I_vBIN = @I_vBIN
, @I_vQUANTITY = @I_vQUANTITY
, @I_vTOBIN = @I_vTOBIN
, @O_iErrorState = @O_iErrorState OUTPUT
, @oErrString = @oErrString OUTPUT";
问题在于参数将按照接收顺序提供给sp。您希望使用sp中的名称将它们分配给sp,这些名称可以相同 执行的sql基本上如下所示:
declare @I_vITEMNMBR char(30) = .. ,
@I_vLOCNCODE char(10) = ..,
@I_vUOFM char(8) = ..,
@I_vBIN char(15) = ..,
@I_vQUANTITY numeric(19, 5) = ..,
@I_vTOBIN char(15) = ..,
@O_iErrorState int,
@oErrString varchar(255)
EXECUTE [dbo].[taIVMultibinBinToBinTransfer]
@I_vITEMNMBR
, @I_vLOCNCODE
, @I_vUOFM
, @I_vBIN
, @I_vQUANTITY
, @I_vTOBIN
, @O_iErrorState OUTPUT
, @oErrString OUTPUT
@正在将I_vUOFM分配给@I_vQTYTYPE,这是错误的类型
你想要的是:
declare @I_vITEMNMBR char(30) = ..,
@I_vLOCNCODE char(10) = ..,
@I_vUOFM char(8) = ..,
@I_vBIN char(15) = ..,
@I_vQUANTITY numeric(19, 5) = ..,
@I_vTOBIN char(15) = ..,
@O_iErrorState int = ..,
@oErrString varchar(255) = ..
EXECUTE [dbo].[taIVMultibinBinToBinTransfer]
@I_vITEMNMBR = @I_vITEMNMBR
, @I_vLOCNCODE = @I_vLOCNCODE
, @I_vUOFM = @I_vUOFM
, @I_vBIN = @I_vBIN
, @I_vQUANTITY = @I_vQUANTITY
, @I_vTOBIN = @I_vTOBIN
, @O_iErrorState = @O_iErrorState OUTPUT
, @oErrString = @oErrString OUTPUT
是的,如果您只想提供这些参数,则必须将代码更改为以下内容:
var spExecQuery = @"EXECUTE [dbo].[taIVMultibinBinToBinTransfer]
@I_vITEMNMBR = @I_vITEMNMBR
, @I_vLOCNCODE = @I_vLOCNCODE
, @I_vUOFM = @I_vUOFM
, @I_vBIN = @I_vBIN
, @I_vQUANTITY = @I_vQUANTITY
, @I_vTOBIN = @I_vTOBIN
, @O_iErrorState = @O_iErrorState OUTPUT
, @oErrString = @oErrString OUTPUT";
可能是一个标志问题。NVARCHAR是两个字节。smallint是带符号位的15位。请尝试删除“执行”文本和sp名称后以文本形式列出的参数。此外,我建议您使用SqlParameter构造函数,该构造函数允许您指定参数类型在我删除sp名称后的参数列表后,我遇到了以下异常:“过程或函数'taivmultibintobuntrasfer'需要参数'@I_vITEMNMBR',但未提供该参数。”我将尝试您告诉我的构造函数。问题可能是符号问题。NVARCHAR为两个字节。smallint为15位,带有符号位。请尝试删除”EXECUTE““text和在sp名称后以text形式列出的参数。另外,我建议您使用SqlParameter构造函数,该构造函数允许您指定参数类型在我删除sp名称后的参数列表后,出现此异常:“过程或函数'TaivMultibinToBurnAsfer'需要参数'@I_vITEMNMBR',但未提供此参数。”我会尝试你告诉我的构造函数。我用我创建的另一个SP测试了这段代码,并进行了一些测试,它工作正常。你是说我应该在我的c函数上硬编码?问题似乎与“sp_executesql”有关,我无法避免任何参数。但我不知道如何强制实体框架不使用它,并像您在示例中所写的那样运行原始查询。ExecuteSqlCommand实际上只是事务中SqlCommand的EF包装器。您正在设置的参数是针对整个命令的,它可以执行任意数量的语句。谢谢,您为我指明了正确的方向。我用SqlCommand修改了代码,我可以让它正常工作。下次如果我必须运行SP,我将使用旧的、可靠的SqlCommand,而不是EFCore新特性。直到现在,我只有在需要做更复杂的事情时才会遇到问题。没问题。我认为您不必使用SqlCommand返回。这将完成所有步骤,对您有用,并将其包装到事务中并管理连接状态。我使用另一个SP测试了此代码,该SP是我为进行一些测试而创建的,它工作正常。你是说我应该在我的c函数上硬编码?问题似乎与“sp_executesql”有关,我无法避免任何参数。但我不知道如何强制实体框架不使用它,并像您在示例中所写的那样运行原始查询。ExecuteSqlCommand实际上只是事务中SqlCommand的EF包装器。您正在设置的参数是针对整个命令的,它可以执行任意数量的语句。谢谢,您为我指明了正确的方向。我用SqlCommand修改了代码,我可以让它正常工作。下次如果我必须运行SP,我将使用旧的、可靠的SqlCommand,而不是EFCore新特性。直到现在,我只有在需要做更复杂的事情时才会遇到问题。没问题。我认为您不必使用SqlCommand返回。这将为您完成所有步骤,并将其包装到事务中,并管理连接状态。