在没有 For 循环的情况下使用 C# 中数据表中的 ID 更新数据库(SQL 服务器)
Updating a DB (SQL Server) using Ids from a dataTable in C# without For loop
这是我关于 S.O 的第一个问题,而且我在 C# 和 SqlServer 方面还是个新手。
太漂亮了,请客气。
我有一个包含 4 列的数据表:id1、id2、id3、id4(和几行)
我还有一个 SQL 服务器数据库,其中包含 4 列和其他列,其中 2 列名为 field1 和 field2
我想将数据库中的 field1 和 field2 更新为 null(不使用 foreach 行)
我已经成功更新了第一行:
public void UpdateDt(DataTable dt, string ConnectionString)
{
Conn = null;
DataRow row = dt.Rows[0]
try
{
Conn = new SqlConnection(ConnectionString);
Conn.Open();
string sql = "update [DB].[dbo].[MyTable] set [field1] = null,"+
"[field2] = null where [ID1] = '"+row["ID1"]+"' and [ID2] = '"+row["ID2"]+"' "+
"and [ID3] = '"+row["ID3"]+"' and [ID4] = '"+row["ID4"]+"'";
var sqlDataAdapter = new SqlDataAdapter { UpdateCommand = Conn.CreateCommand() };
sqlDataAdapter.UpdateCommand.CommandText = sql;
sqlDataAdapter.UpdateCommand.BeginExecuteNonQuery();
}
catch( Exception ex) log(ex);
finally
{
if (Conn != null)
{
Conn.Close();
Conn.Dispose();
}
}
}
如何使用整个 DataTable 进行更新?
请帮忙
提前致谢
-- 对 Soner Gönül 评论的回应
我已经根据您的建议修改了示例代码,谢谢
Zohar,谢谢,我选择了字段名称是为了尝试让问题更笼统和更容易理解
---编辑---
我添加了使用 ForEach 更新整个 DataTable 的代码(在 Russ 的帮助下(感谢 Russ))
bool UpdateDt(DataTable dt)
{
Conn = null;
try
{
Conn = new SqlConnection(ConnectionString);
Conn.Open();
string sql = "update [KeywordInjectionData] " +
"set " +
"[field1] = null " +
",[field2] = null " +
"where " +
"[Id1] = @Id1" +
" and [Id2] = @Id2" +
" and [Id3] = @Id3" +
" and [Id4] = @Id4;" ;
var sqlDataAdapter = new SqlDataAdapter { UpdateCommand = Conn.CreateCommand() };
foreach (DataRow row in dt.Rows)
{
sqlDataAdapter.UpdateCommand.CommandText = sql;
sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("@Id1",row["Id1"]);
sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("@Id2",row["Id2"]);
sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("@Id3",row["Id3"]);
sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("@Id4",row["Id4"]);
sqlDataAdapter.UpdateCommand.ExecuteNonQuery();
sqlDataAdapter.UpdateCommand.Parameters.Clear();
}
}
catch (Exception e1)
{
Utillties.LogError(e1);
return false;
}
finally
{
if (Conn != null)
{
Conn.Close();
Conn.Dispose();
}
}
return true;
}
但问题仍然存在,如何在没有 ForEach 循环的情况下更新数据库?
首先,您构建查询的方式非常危险,因为它会允许 SQL 注入——您应该只使用参数化查询(正如 Soner Gonul 在上面的评论中提到的)。
其次,您可以使用 Foreach 子句遍历每一行:
Foreach (DataRow row in dt.Rows)
然而,在执行此操作时,您应该将连接声明和打开移动到 Foreach 之前,以便您只打开连接一次。
我不确定您为什么不想在这种情况下使用循环。一般来说,在纯数据库级别,循环被认为是 "bad",但这实际上是对问题的过度简化......(我写了很多查询,有循环比没有循环更快)
让我们从问题中删除 C# 开始,改为 "how to update all desired rows in a table at once?" 因为新值都是相同的,所以这是可能的,前提是您可以创建适当的 where
子句。在这种情况下,由于您试图根据(我假设)用户输入更新一组随机行,因此它需要如下所示:
UPDATE dbo.MyTable
SET field1 = null, field2 = null
WHERE (id1 = @m1_id1 AND id2 = @m1_id2 AND id3 = @m1_id3)
OR (id1 = @m2_id1 AND id2 = @m2_id2 AND id3 = @m2_id3)
OR (id1 = @m3_id1 AND id2 = @m3_id2 AND id3 = @m3_id3)
etc.
这很愚蠢而且很快。为了完整起见,如果您在数据库中引用另一个 table,则可以执行以下操作(在大多数 RDBMS 下):
UPDATE myT
SET field1 = null, field2 = null
FROM dbo.MyTable myT
JOIN dbo.SetsToUpdate s ON myT.id1=s.id1
AND myT.id2=s.id2
AND myT.id3=s.id3
但是,您并不是从另一个 table 开始,设置一个、填充它并清理它很可能需要比简单的多个单行更新更多的资源。
所以,我们回到了一个循环,但是在 C# 中执行的循环非常有效。此外,除了性能之外,需要单个 update
语句的唯一其他原因是数据原子性,transactions
.
可以很好地处理它
如果您确实在此处看到数据库级别的性能问题,那么问题就是数据库优化之一(查看 indexes
)。但是,请不要陷入过早优化的陷阱。
这是我关于 S.O 的第一个问题,而且我在 C# 和 SqlServer 方面还是个新手。 太漂亮了,请客气。
我有一个包含 4 列的数据表:id1、id2、id3、id4(和几行) 我还有一个 SQL 服务器数据库,其中包含 4 列和其他列,其中 2 列名为 field1 和 field2
我想将数据库中的 field1 和 field2 更新为 null(不使用 foreach 行)
我已经成功更新了第一行:
public void UpdateDt(DataTable dt, string ConnectionString)
{
Conn = null;
DataRow row = dt.Rows[0]
try
{
Conn = new SqlConnection(ConnectionString);
Conn.Open();
string sql = "update [DB].[dbo].[MyTable] set [field1] = null,"+
"[field2] = null where [ID1] = '"+row["ID1"]+"' and [ID2] = '"+row["ID2"]+"' "+
"and [ID3] = '"+row["ID3"]+"' and [ID4] = '"+row["ID4"]+"'";
var sqlDataAdapter = new SqlDataAdapter { UpdateCommand = Conn.CreateCommand() };
sqlDataAdapter.UpdateCommand.CommandText = sql;
sqlDataAdapter.UpdateCommand.BeginExecuteNonQuery();
}
catch( Exception ex) log(ex);
finally
{
if (Conn != null)
{
Conn.Close();
Conn.Dispose();
}
}
}
如何使用整个 DataTable 进行更新?
请帮忙 提前致谢
-- 对 Soner Gönül 评论的回应
我已经根据您的建议修改了示例代码,谢谢
Zohar,谢谢,我选择了字段名称是为了尝试让问题更笼统和更容易理解
---编辑--- 我添加了使用 ForEach 更新整个 DataTable 的代码(在 Russ 的帮助下(感谢 Russ))
bool UpdateDt(DataTable dt)
{
Conn = null;
try
{
Conn = new SqlConnection(ConnectionString);
Conn.Open();
string sql = "update [KeywordInjectionData] " +
"set " +
"[field1] = null " +
",[field2] = null " +
"where " +
"[Id1] = @Id1" +
" and [Id2] = @Id2" +
" and [Id3] = @Id3" +
" and [Id4] = @Id4;" ;
var sqlDataAdapter = new SqlDataAdapter { UpdateCommand = Conn.CreateCommand() };
foreach (DataRow row in dt.Rows)
{
sqlDataAdapter.UpdateCommand.CommandText = sql;
sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("@Id1",row["Id1"]);
sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("@Id2",row["Id2"]);
sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("@Id3",row["Id3"]);
sqlDataAdapter.UpdateCommand.Parameters.AddWithValue("@Id4",row["Id4"]);
sqlDataAdapter.UpdateCommand.ExecuteNonQuery();
sqlDataAdapter.UpdateCommand.Parameters.Clear();
}
}
catch (Exception e1)
{
Utillties.LogError(e1);
return false;
}
finally
{
if (Conn != null)
{
Conn.Close();
Conn.Dispose();
}
}
return true;
}
但问题仍然存在,如何在没有 ForEach 循环的情况下更新数据库?
首先,您构建查询的方式非常危险,因为它会允许 SQL 注入——您应该只使用参数化查询(正如 Soner Gonul 在上面的评论中提到的)。
其次,您可以使用 Foreach 子句遍历每一行:
Foreach (DataRow row in dt.Rows)
然而,在执行此操作时,您应该将连接声明和打开移动到 Foreach 之前,以便您只打开连接一次。
我不确定您为什么不想在这种情况下使用循环。一般来说,在纯数据库级别,循环被认为是 "bad",但这实际上是对问题的过度简化......(我写了很多查询,有循环比没有循环更快)
让我们从问题中删除 C# 开始,改为 "how to update all desired rows in a table at once?" 因为新值都是相同的,所以这是可能的,前提是您可以创建适当的 where
子句。在这种情况下,由于您试图根据(我假设)用户输入更新一组随机行,因此它需要如下所示:
UPDATE dbo.MyTable
SET field1 = null, field2 = null
WHERE (id1 = @m1_id1 AND id2 = @m1_id2 AND id3 = @m1_id3)
OR (id1 = @m2_id1 AND id2 = @m2_id2 AND id3 = @m2_id3)
OR (id1 = @m3_id1 AND id2 = @m3_id2 AND id3 = @m3_id3)
etc.
这很愚蠢而且很快。为了完整起见,如果您在数据库中引用另一个 table,则可以执行以下操作(在大多数 RDBMS 下):
UPDATE myT
SET field1 = null, field2 = null
FROM dbo.MyTable myT
JOIN dbo.SetsToUpdate s ON myT.id1=s.id1
AND myT.id2=s.id2
AND myT.id3=s.id3
但是,您并不是从另一个 table 开始,设置一个、填充它并清理它很可能需要比简单的多个单行更新更多的资源。
所以,我们回到了一个循环,但是在 C# 中执行的循环非常有效。此外,除了性能之外,需要单个 update
语句的唯一其他原因是数据原子性,transactions
.
如果您确实在此处看到数据库级别的性能问题,那么问题就是数据库优化之一(查看 indexes
)。但是,请不要陷入过早优化的陷阱。