无法将数据从 JSON 插入 SQL 服务器 table
Unable to insert data from the JSON in to the SQL server table
我正在尝试创建一个调用 REST API 并将响应插入到 Azure SQL 服务器 table 的 SSIS 包。为此,我正在使用脚本任务和 ADO.NET 连接管理器。 API 响应采用 JSON 格式,如下所示
{[
{"id": 1, "name": "AX", "description": "B", "shippingFreeze": false, "receivingFreeze": false, "mouseNorovirus": false, "irradiatedFeed": true, "createdAt": "2022-02-24T10:03:50.09", "lastUpdated": "2022-02-24T10:03:50.09" },
{"id": 2, "name": "PD ", "description": "F", "shippingFreeze": false, "receivingFreeze": false, "mouseNorovirus": false, "irradiatedFeed": false, "createdAt": "2022-02-24T10:03:50.09", "lastUpdated": "2022-02-24T10:03:50.09" }
]}
Table 在 SQL 服务器中
我正在尝试遍历 JSON 并将它们中的每一个插入到 SQL 服务器 tables,如下所示
var result = response.Content.ReadAsStringAsync().Result;
dynamic res_JSON = JsonConvert.DeserializeObject(result);
ConnectionManager cm = Dts.Connections["SurplusMouse_ADONET"];
var sqlConn = (System.Data.SqlClient.SqlConnection)cm.AcquireConnection(Dts.Transaction);
using (var sqlCmd = new System.Data.SqlClient.SqlCommand("INSERT INTO [dbo].[RM_Room]([ROOMID],[NAME],[DESCRIPTION],[SHIPPING_FREEZE],[RECEIVING_FREEZE],[MOUSE_NOROVIRUS],[IRRADIATED_FEED]) VALUES(@ROOMID,@NAME,@DESCRIPTION,@SHIPPING_FREEZE,@RECEIVING_FREEZE,@MOUSE_NOROVIRUS,@IRRADIATED_FEED,)", sqlConn))
{
foreach (var jsonObj in res_JSON)
{
sqlCmd.CommandType = CommandType.Text;
sqlCmd.Parameters.AddWithValue("@ROOMID", jsonObj.id.ToString());
sqlCmd.Parameters.AddWithValue("@NAME", jsonObj.name.ToString());
sqlCmd.Parameters.AddWithValue("@DESCRIPTION", jsonObj.description.ToString());
sqlCmd.Parameters.AddWithValue("@SHIPPING_FREEZE", (jsonObj.shippingFreeze.ToString() == "true") ? "T" : "F");
sqlCmd.Parameters.AddWithValue("@RECEIVING_FREEZE", (jsonObj.receivingFreeze.ToString() == "true") ? "T" : "F");
sqlCmd.Parameters.AddWithValue("@MOUSE_NOROVIRUS", (jsonObj.mouseNorovirus.ToString() == "true") ? "T" : "F");
sqlCmd.Parameters.AddWithValue("@IRRADIATED_FEED", (jsonObj.irradiatedFeed.ToString() == "true") ? "T" : "F");
int no_exec = sqlCmd.ExecuteNonQuery();
}
}
cm.ReleaseConnection(sqlConn);
}}
catch (Exception ex)
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
当我调试时抛出类似
的错误
和堆栈跟踪
at System.Data.SqlClient.SqlConnection.OnError(SqlException 异常,Boolean breakConnection,Action1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action
1 wrapCloseInAction)
在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj,布尔调用者有连接锁,布尔异步关闭)
在 System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior、SqlCommand cmdHandler、SqlDataReader dataStream、BulkCopySimpleResultSet bulkCopyHandler、TdsParserStateObject stateObj、Boolean& dataReady)
在 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds、RunBehavior runBehavior、字符串 resetOptionsString、布尔值 isInternal、布尔值 forDescribeParameterEncryption、布尔值 shouldCacheForAlwaysEncrypted)
在 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、Boolean async、Int32 timeout、Task& task、Boolean asyncWrite、Boolean inRetry、SqlDataReader ds、Boolean describeParameterEncryptionRequest)
在 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、String 方法、TaskCompletionSource1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource
1 完成、String methodName、Boolean sendToPipe、Int32 超时、Boolean& usedCache、Boolean asyncWrite、Boolean inRetry)
在 System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
在 ST_b0ab9fccfaa640008ecd1bdf57ec4324.ScriptMain.Main() 在 C:\Users\dv_admin\AppData\Local\Temp\vstaff553a1bba27\ScriptMain.cs:line 76
我不确定我在这里缺少什么。非常感谢任何帮助
更新代码
public async void Main()
{
try
{
var sqlConn = new System.Data.SqlClient.SqlConnection();
ConnectionManager cm = Dts.Connections["SurplusMouse_ADONET"];
string serviceUrl = Dts.Variables["$Project::ServiceUrl"].Value.ToString();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(serviceUrl);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
string APIUrl = string.Format(serviceUrl + "/rooms");
var response = client.GetAsync(APIUrl).Result;
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
try
{
sqlConn = (System.Data.SqlClient.SqlConnection)cm.AcquireConnection(Dts.Transaction);
const string query = @"INSERT INTO dbo.RM_Room
(ROOMID, NAME, DESCRIPTION, SHIPPING_FREEZE, RECEIVING_FREEZE, MOUSE_NOROVIRUS, IRRADIATED_FEED)
SELECT id, name, description,
CASE shippingFreeze WHEN 1 THEN 'T' ELSE 'F' END,
CASE receivingFreeze WHEN 1 THEN 'T' ELSE 'F' END,
CASE mouseNorovirus WHEN 1 THEN 'T' ELSE 'F' END,
CASE irradiatedFeed WHEN 1 THEN 'T' ELSE 'F' END
FROM OPENJSON(@json)
WITH (
id int,
name varchar(100),
description varchar(1000),
shippingFreeze bit,
receivingFreeze bit,
mouseNorovirus bit,
irradiatedFeed bit
) j;";
using (var sqlCmd = new System.Data.SqlClient.SqlCommand(query, sqlConn))
{
sqlCmd.Parameters.Add("@json", SqlDbType.NVarChar, -1).Value = result;
await sqlConn.OpenAsync();
await sqlCmd.ExecuteNonQueryAsync();
}
}
catch (Exception ex)
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
finally
{
if (sqlConn != null)
cm.ReleaseConnection(sqlConn);
}
}
}
catch (Exception ex)
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
}
您的主要问题是 SQL 中多了一个逗号,这是一个语法错误。
将整个 JSON 传递给 SQL 服务器并使用 OPENJSON
粉碎它可能更容易
var result = await response.Content.ReadAsStringAsync();
ConnectionManager cm = Dts.Connections["SurplusMouse_ADONET"];
SqlConnection sqlConn = null;
try
{
sqlConn = (SqlConnection)cm.AcquireConnection(Dts.Transaction));
const string query = @"
INSERT INTO dbo.RM_Room
(ROOMID, NAME, DESCRIPTION, SHIPPING_FREEZE, RECEIVING_FREEZE, MOUSE_NOROVIRUS, IRRADIATED_FEED)
SELECT
id,
name,
description,
CASE shippingFreeze WHEN 1 THEN 'T' ELSE 'F' END,
CASE receivingFreeze WHEN 1 THEN 'T' ELSE 'F' END,
CASE mouseNorovirus WHEN 1 THEN 'T' ELSE 'F' END,
CASE irradiatedFeed WHEN 1 THEN 'T' ELSE 'F' END
FROM OPENJSON(@json)
WITH (
id int,
name varchar(100),
description varchar(1000),
shippingFreeze bit,
receivingFreeze bit,
mouseNorovirus bit,
irradiatedFeed bit
) j;
";
using (var sqlCmd = new SqlCommand(query, sqlConn))
{
sqlCmd.Parameters.Add("@json", SqlDbType.NVarChar, -1).Value = result;
await sqlCmd.ExecuteNonQueryAsync();
}
}
catch (Exception ex)
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
finally
{
if(sqlConn != null)
cm.ReleaseConnection(sqlConn);
}
备注:
sqlCmd.CommandType = CommandType.Text
是不必要的。
ReleaseConnection
需要在 finally
- 尽管不清楚您一开始为什么要使用
ConnectionManager
。您可能应该直接创建 SqlConnection
,然后将其放入 using
- 避免
AddWithValue
,而是明确指定类型和长度。
- 使用
Async
版本的代码 await
。 不要调用.Result
,否则你可能会死锁。
我正在尝试创建一个调用 REST API 并将响应插入到 Azure SQL 服务器 table 的 SSIS 包。为此,我正在使用脚本任务和 ADO.NET 连接管理器。 API 响应采用 JSON 格式,如下所示
{[
{"id": 1, "name": "AX", "description": "B", "shippingFreeze": false, "receivingFreeze": false, "mouseNorovirus": false, "irradiatedFeed": true, "createdAt": "2022-02-24T10:03:50.09", "lastUpdated": "2022-02-24T10:03:50.09" },
{"id": 2, "name": "PD ", "description": "F", "shippingFreeze": false, "receivingFreeze": false, "mouseNorovirus": false, "irradiatedFeed": false, "createdAt": "2022-02-24T10:03:50.09", "lastUpdated": "2022-02-24T10:03:50.09" }
]}
Table 在 SQL 服务器中
我正在尝试遍历 JSON 并将它们中的每一个插入到 SQL 服务器 tables,如下所示
var result = response.Content.ReadAsStringAsync().Result;
dynamic res_JSON = JsonConvert.DeserializeObject(result);
ConnectionManager cm = Dts.Connections["SurplusMouse_ADONET"];
var sqlConn = (System.Data.SqlClient.SqlConnection)cm.AcquireConnection(Dts.Transaction);
using (var sqlCmd = new System.Data.SqlClient.SqlCommand("INSERT INTO [dbo].[RM_Room]([ROOMID],[NAME],[DESCRIPTION],[SHIPPING_FREEZE],[RECEIVING_FREEZE],[MOUSE_NOROVIRUS],[IRRADIATED_FEED]) VALUES(@ROOMID,@NAME,@DESCRIPTION,@SHIPPING_FREEZE,@RECEIVING_FREEZE,@MOUSE_NOROVIRUS,@IRRADIATED_FEED,)", sqlConn))
{
foreach (var jsonObj in res_JSON)
{
sqlCmd.CommandType = CommandType.Text;
sqlCmd.Parameters.AddWithValue("@ROOMID", jsonObj.id.ToString());
sqlCmd.Parameters.AddWithValue("@NAME", jsonObj.name.ToString());
sqlCmd.Parameters.AddWithValue("@DESCRIPTION", jsonObj.description.ToString());
sqlCmd.Parameters.AddWithValue("@SHIPPING_FREEZE", (jsonObj.shippingFreeze.ToString() == "true") ? "T" : "F");
sqlCmd.Parameters.AddWithValue("@RECEIVING_FREEZE", (jsonObj.receivingFreeze.ToString() == "true") ? "T" : "F");
sqlCmd.Parameters.AddWithValue("@MOUSE_NOROVIRUS", (jsonObj.mouseNorovirus.ToString() == "true") ? "T" : "F");
sqlCmd.Parameters.AddWithValue("@IRRADIATED_FEED", (jsonObj.irradiatedFeed.ToString() == "true") ? "T" : "F");
int no_exec = sqlCmd.ExecuteNonQuery();
}
}
cm.ReleaseConnection(sqlConn);
}}
catch (Exception ex)
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
当我调试时抛出类似
的错误和堆栈跟踪
at System.Data.SqlClient.SqlConnection.OnError(SqlException 异常,Boolean breakConnection,Action1 wrapCloseInAction) at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action
1 wrapCloseInAction)
在 System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj,布尔调用者有连接锁,布尔异步关闭)
在 System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior、SqlCommand cmdHandler、SqlDataReader dataStream、BulkCopySimpleResultSet bulkCopyHandler、TdsParserStateObject stateObj、Boolean& dataReady)
在 System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds、RunBehavior runBehavior、字符串 resetOptionsString、布尔值 isInternal、布尔值 forDescribeParameterEncryption、布尔值 shouldCacheForAlwaysEncrypted)
在 System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、Boolean async、Int32 timeout、Task& task、Boolean asyncWrite、Boolean inRetry、SqlDataReader ds、Boolean describeParameterEncryptionRequest)
在 System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior、RunBehavior runBehavior、Boolean returnStream、String 方法、TaskCompletionSource1 completion, Int32 timeout, Task& task, Boolean& usedCache, Boolean asyncWrite, Boolean inRetry) at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(TaskCompletionSource
1 完成、String methodName、Boolean sendToPipe、Int32 超时、Boolean& usedCache、Boolean asyncWrite、Boolean inRetry)
在 System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
在 ST_b0ab9fccfaa640008ecd1bdf57ec4324.ScriptMain.Main() 在 C:\Users\dv_admin\AppData\Local\Temp\vstaff553a1bba27\ScriptMain.cs:line 76
我不确定我在这里缺少什么。非常感谢任何帮助
更新代码
public async void Main()
{
try
{
var sqlConn = new System.Data.SqlClient.SqlConnection();
ConnectionManager cm = Dts.Connections["SurplusMouse_ADONET"];
string serviceUrl = Dts.Variables["$Project::ServiceUrl"].Value.ToString();
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(serviceUrl);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
string APIUrl = string.Format(serviceUrl + "/rooms");
var response = client.GetAsync(APIUrl).Result;
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
try
{
sqlConn = (System.Data.SqlClient.SqlConnection)cm.AcquireConnection(Dts.Transaction);
const string query = @"INSERT INTO dbo.RM_Room
(ROOMID, NAME, DESCRIPTION, SHIPPING_FREEZE, RECEIVING_FREEZE, MOUSE_NOROVIRUS, IRRADIATED_FEED)
SELECT id, name, description,
CASE shippingFreeze WHEN 1 THEN 'T' ELSE 'F' END,
CASE receivingFreeze WHEN 1 THEN 'T' ELSE 'F' END,
CASE mouseNorovirus WHEN 1 THEN 'T' ELSE 'F' END,
CASE irradiatedFeed WHEN 1 THEN 'T' ELSE 'F' END
FROM OPENJSON(@json)
WITH (
id int,
name varchar(100),
description varchar(1000),
shippingFreeze bit,
receivingFreeze bit,
mouseNorovirus bit,
irradiatedFeed bit
) j;";
using (var sqlCmd = new System.Data.SqlClient.SqlCommand(query, sqlConn))
{
sqlCmd.Parameters.Add("@json", SqlDbType.NVarChar, -1).Value = result;
await sqlConn.OpenAsync();
await sqlCmd.ExecuteNonQueryAsync();
}
}
catch (Exception ex)
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
finally
{
if (sqlConn != null)
cm.ReleaseConnection(sqlConn);
}
}
}
catch (Exception ex)
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
}
您的主要问题是 SQL 中多了一个逗号,这是一个语法错误。
将整个 JSON 传递给 SQL 服务器并使用 OPENJSON
var result = await response.Content.ReadAsStringAsync();
ConnectionManager cm = Dts.Connections["SurplusMouse_ADONET"];
SqlConnection sqlConn = null;
try
{
sqlConn = (SqlConnection)cm.AcquireConnection(Dts.Transaction));
const string query = @"
INSERT INTO dbo.RM_Room
(ROOMID, NAME, DESCRIPTION, SHIPPING_FREEZE, RECEIVING_FREEZE, MOUSE_NOROVIRUS, IRRADIATED_FEED)
SELECT
id,
name,
description,
CASE shippingFreeze WHEN 1 THEN 'T' ELSE 'F' END,
CASE receivingFreeze WHEN 1 THEN 'T' ELSE 'F' END,
CASE mouseNorovirus WHEN 1 THEN 'T' ELSE 'F' END,
CASE irradiatedFeed WHEN 1 THEN 'T' ELSE 'F' END
FROM OPENJSON(@json)
WITH (
id int,
name varchar(100),
description varchar(1000),
shippingFreeze bit,
receivingFreeze bit,
mouseNorovirus bit,
irradiatedFeed bit
) j;
";
using (var sqlCmd = new SqlCommand(query, sqlConn))
{
sqlCmd.Parameters.Add("@json", SqlDbType.NVarChar, -1).Value = result;
await sqlCmd.ExecuteNonQueryAsync();
}
}
catch (Exception ex)
{
Dts.TaskResult = (int)ScriptResults.Failure;
}
finally
{
if(sqlConn != null)
cm.ReleaseConnection(sqlConn);
}
备注:
sqlCmd.CommandType = CommandType.Text
是不必要的。ReleaseConnection
需要在finally
- 尽管不清楚您一开始为什么要使用
ConnectionManager
。您可能应该直接创建SqlConnection
,然后将其放入using
- 避免
AddWithValue
,而是明确指定类型和长度。 - 使用
Async
版本的代码await
。 不要调用.Result
,否则你可能会死锁。