Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/302.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在一个连接中执行多个UPDATE语句的最佳方法是什么?_C#_Oracle_Odp.net_Update Statement - Fatal编程技术网

C# 在一个连接中执行多个UPDATE语句的最佳方法是什么?

C# 在一个连接中执行多个UPDATE语句的最佳方法是什么?,c#,oracle,odp.net,update-statement,C#,Oracle,Odp.net,Update Statement,如何正确执行以下更新: using (OracleConnection conn = new OracleConnection()) using (selCmd) { string sql1 = "update Table1 set name = joe where id = 10;" string sql2 = "update Table2 set country = usa where region = americas;" string sql3 = "updat

如何正确执行以下更新:

using (OracleConnection conn = new OracleConnection())
using (selCmd)
{

    string sql1 = "update Table1 set name = joe where id = 10;"
    string sql2 = "update Table2 set country = usa where region = americas;"
    string sql3 = "update Table3 set weather = sunny where state = CA;"
    string sql4 = "update Table4 set engine = v8 where maker = benz;"

    cmdUpdate.CommandText = sql(#);
    cmdUpdate.Connection = conn;
    recs = cmdUpdate.ExecuteNonQuery();
}
如果这是一项交易,我知道全部或全部,但我只是想看看它如何以正确的方式工作


我想迭代一个项目数组[sql1、sql2、sql3、sql4],并在CommandText中传递sql(#),每次执行ExecuteOnQuery。

如果我没记错的话,可以将多个sql语句串联在一个由分号(;)分隔的字符串中。否则,执行多个
ExecuteNonQuery()
调用没有什么错

string sql1 = "BEGIN update Table1 set name = 'joe' where id = 10;",
       sql2 = "update Table2 set country = 'usa' where region = 'americas';",
       sql3 = "update Table3 set weather = 'sunny' where state = 'CA';",
       sql4 = "update Table4 set engine = 'v8' where maker = 'benz'; END;";

string sql = string.Format("{0}{1}{2}{3}",sql1,sql2,sql3,sql4);

using (OracleConnection conn = new OracleConnection())
using (OracleCommand cmdUpdate = new OracleCommand(sql, conn))
{
    conn.Open();
    recs = cmdUpdate.ExecuteNonQuery();
}

另一种方法是创建一个简单的扩展方法(ExecuteMultipleNonQuery),该方法简单地拆分所有分号上的字符串,并在循环中执行每条语句:

public static class DbCommandExtensions {

    public static void ExecuteMultipleNonQuery(this IDbCommand dbCommand)
    {
        var sqlStatementArray = dbCommand.CommandText.Split(new string[] {";"}, StringSplitOptions.RemoveEmptyEntries);
        foreach (string sqlStatement in sqlStatementArray)
        {
            dbCommand.CommandText = sqlStatement;
            dbCommand.ExecuteNonQuery();
        }
    }

}

我最近在一些旧代码中遇到了这个问题。我们动态构建SQL调用链(支持Oracle和SQL Server)。由于目前没有Oracle生产实施,因此没有人测试Oracle操作,客户的bug也没有出现。我找到了一个构建命令链的代码,然后,对于Oracle,它使用
String.Split(“;”)
。然后,它使用一个循环来执行事务中的每个语句:
rowsafecter+=ExecuteNonQuery….

我不喜欢这个想法,因为没有参数化,这是一种危险的方法,因为有些数据可能包含
。但即使参数化已经到位

。。。为Oracle(
开始…结束;“
)生成匿名块的问题之一是
ExecuteOnQuery
不会返回行数(返回-1),有时需要返回行数来判断是否更新了某些内容

为了解决这个问题,我已经这样做了

private string AppendOracleCountOrNothing(StringBuilder sql)
{
    if (_myProvider == Providers.Oracle)
        sql.AppendLine("rowCnt := rowCnt + SQL%ROWCOUNT;");
}


public void SomeMethod()
{
    var longSqlChain = new StringBuilder(2000);

    longSqlChain.Append("Insert into table...;");
    AppendOracleCountOrNothing(longSqlChain);
    if (someCondition)
    {
        longSqlChain.AppendLine("Update anotherTable...;");
        AppendOracleCountOrNothing(longSqlChain);
    } 

    // may be, add some more sql to longSqlChain here....

    int rowsAffected;
    if (_myProvider == Providers.Oracle)
    {
        longSqlChain.Insert(0, @"DECLARE
            rowCnt number(10) := 0
            BEGIN
            ").AppendLine(@":1 := rowCnt;
            END;");
        // Now, here we have some abstract wrappers that hide provider specific code. 
        // But the idea is to prepare provider specific output parameter and then parse its value
        IDataParameter p = ParameterWrapper.PrepareParameter(":1", 0, ParameterDirection.Output, myProvider); // note IDataParameter 
        SqlExecWrapper.ExecuteNonQuery(_myProvider, CommandType.Text, sql, new[]{p});
        rowsAffected = p.GetParameterValue(); // GetParameterValue is an extension on IDataParameter 
    }
    else // sql server
    {
        rowsAffected = SqlExecWrapper.ExecuteNonQuery(_myProvider, CommandType.Text, sql, null);
    }
}

这样,我们只需访问DB一次,就可以得到受此调用影响的返回行数。查询也可以参数化。同样,最好开发抽象层,因此,您可以在sql语句中调用类似于
parameterizer.CreateParameter(10)
,它将向集合添加参数并生成
:1、:2、:3等。
(oracle)和
@1、@2、@3等。
(sql server),除了你的sql字符串没有“终止。这很奇怪…代码sytax stlye一定改变了我的代码块。我会修复它。Thx用于反馈Xander。我编辑了你的标题。请参阅“”,其中一致意见是“不,他们不应该”“.selCmd
的意思是什么?对不起,selCmd只是我为IDbCommand准备的一个变量。您的解决方案可以很好地工作,只需稍作调整即可:1)添加:在第一次更新之前开始(因此”string sql1=“BEGIN UPDATE…”2)添加:END;在contated语句的最末尾(因此“…”benz“;END;”3)我必须反转OracleCommand(sql,conn)这没什么大不了的,谢谢你们帮我找到了正确的方向。这非常有用!谢谢你们的反馈。我只是凭记忆写的。希望其他人能发现它有用。当然,只要你的数据不是这样的,它就会一直起作用:
'lalalala;噢,伙计。
是的,当然,你是对的,也许可以告诉我们使用要求分号作为行尾的正则表达式?SQL语句可以一个接一个地写入,而不需要换行。您可以检查
”;“
不在单引号
”;“
内,下一个单词是
更新/插入/删除
。这比盲目的
拆分(;”)
要好。底线是,在当前形式下,您的答案的代码容易出问题。