c# - 将对象列表传递给 SQL Server 存储过程并检索输出值
问题描述
我正在尝试使用 ado.net 将对象列表以及其他一些数字和字符串参数传递给 SQL Server 存储过程并执行它,并从输出参数中检索一个值。
为了从 SQL Server 存储过程中捕获对象列表,我使用了用户定义的表类型,如下所示:
这是存储过程:
ALTER PROCEDURE [dbo].[UpdateMailjetDetails]
@listCode VARCHAR(1000),
@listName VARCHAR(1000),
@mailjetListId BIGINT,
@mailjetListStatus INT,
@autoAsync BIT,
@contacts Contact READONLY,
@companyId INT,
@tblContactCompanyStatus INT,
@espListContactStatus INT,
@outputMessage VARCHAR(1000) OUT
AS
BEGIN
SET NOCOUNT ON;
BEGIN TRANSACTION [Tran1]
BEGIN TRY
-- logic
--
--
SET @outputMessage = 'success';
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION [Tran1];
SELECT
'Error - Rollbacked -' AS CustomMessage,
ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
SET @outputMessage = 'error - ' + ERROR_MESSAGE();
END CATCH
END
这是调用存储过程的 C# 代码。
public string SaveAndPassToMailjetWindowsService(string listCode, string listName, long mailjetListId, MailjetListStatus mailjetListStatus, bool autoSync, List<Contact> contacts, int companyId, TblContactCompanyStatus tblContactCompanyStatus, EspListContactStatus espListContactStatus)
{
try
{
string result;
var conString = GetMailCoreConnectionString();
using (var conn = new SqlConnection(conString))
{
var command = new SqlCommand("UpdateMailjetDetails", conn)
{ CommandType = CommandType.StoredProcedure };
command.Parameters.Add(new SqlParameter("@listCode", listCode));
command.Parameters.Add(new SqlParameter("@listName", listName));
command.Parameters.Add(new SqlParameter("@mailjetListId", mailjetListId));
command.Parameters.Add(new SqlParameter("@mailjetListStatus", (int) mailjetListStatus));
command.Parameters.Add(new SqlParameter("@autoAsync", autoSync));
var contactsParam =
new SqlParameter("@contacts", SqlDbType.Structured)
{
TypeName = "dbo.Contact",
Value = GetSqlDataRecordsContactsList(contacts)
};
command.Parameters.Add(new SqlParameter("@contacts", contactsParam));
command.Parameters.Add(new SqlParameter("@companyId", companyId));
command.Parameters.Add(new SqlParameter("@tblContactCompanyStatus", (int) tblContactCompanyStatus));
command.Parameters.Add(new SqlParameter("@espListContactStatus", (int) espListContactStatus));
var outputParameter = new SqlParameter
{
ParameterName = "@outputMessage",
SqlDbType = SqlDbType.VarChar,
Direction = ParameterDirection.Output
};
command.Parameters.Add(outputParameter);
conn.Open();
command.ExecuteNonQuery(); // throws exception
result = outPutParameter.Value.ToString();
conn.Close();
}
return result;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
下面是将联系人列表转换为数据表的 C# 方法。
private List<SqlDataRecord> GetSqlDataRecordsContactsList(List<Contact> contacts)
{
try
{
List<SqlDataRecord> datatable = new List<SqlDataRecord>();
SqlMetaData[] sqlMetaData = new SqlMetaData[5];
sqlMetaData[0] = new SqlMetaData("Email", SqlDbType.NVarChar, 512);
sqlMetaData[1] = new SqlMetaData("Name", SqlDbType.NVarChar, 512);
sqlMetaData[2] = new SqlMetaData("TblContactId", SqlDbType.BigInt);
sqlMetaData[3] = new SqlMetaData("CompanyId", SqlDbType.Int);
sqlMetaData[4] = new SqlMetaData("TblContactCompanyId", SqlDbType.BigInt);
foreach (var contact in contacts)
{
SqlDataRecord row = new SqlDataRecord(sqlMetaData);
row.SetValues(contact.Email, contact.Name, contact.TblContactId ?? (object) DBNull.Value,
contact.CompanyId ?? (object) DBNull.Value,
contact.TblContactCompanyId ?? (object) DBNull.Value);
datatable.Add(row);
}
return datatable;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
现在,当我运行代码时,它会正确执行存储过程中的所有逻辑并完成我想要做的所有更改。我可以看到已经通过存储过程正确添加了数据,但是SaveAndPassToMailjetWindowsService
方法
command.ExecuteNonQuery();
在 C# 端引发异常(即使存储过程正确执行其逻辑)。
不存在从对象类型 System.Data.SqlClient.SqlParameter 到已知托管提供程序本机类型的映射。
非常感谢任何解决此问题的指导。谢谢。
解决方案
在这里,您将参数添加为参数的值:
var contactsParam =
new SqlParameter("@contacts", SqlDbType.Structured)
{
TypeName = "dbo.Contact",
Value = GetSqlDataRecordsContactsList(contacts)
};
command.Parameters.Add(new SqlParameter("@contacts", contactsParam)); //Problem is here
它应该只是:
command.Parameters.Add(contactsParam);
推荐阅读
- javascript - React / Redux - 发送多个补丁请求 onBlur
- javascript - 如何修复重叠的地图标记?
- security - Thorntail MP JWT / Undertow:需要身份验证
- python - Python networkx 图标签
- vue.js - 使用 v-bind 和 v-on 代替 v-model vuejs
- android - SQLite NOT NULL 约束失败 - 如何解决?
- javascript - JQuery语法异同
- c++ - 通过 emplace() 将对象指针插入地图地图不起作用
- stripe-payments - 何时从条带事件更新数据库中的订阅结束日期
- c - 如何在不暴露其类型的情况下暴露 C 结构大小?