使用C#执行Oracle SQL脚本

时间:2018-08-14 05:34:43

标签: c# oracle tfs deployment

我正在研究C#的大型解决方案。该解决方案使用不同的oracle数据库,并已在TFS中签入。实际上,我开发了一个小型库,该库可以将解决方案中的SQL脚本部署到使用的数据库。应用程序的部署由TFS处理,将来我的工具应该包含在构建过​​程中。对于Oracle Connection,执行语句使用Oracle.ManagedDataAccess.Client。

如果SQL文件中只有几个DDL或DML语句,则第一个测试成功。但是我必须处理一些特殊的特殊事项,例如SET DEFINE OFF。这不是真正的SQL语句,如果我使用ORacle SQL * PLus运行脚本,则没有问题。在一开始,我尝试执行整个脚本,但是这不起作用,因为我的应用程序将多条语句放在一行中,而我发现的唯一解决方案是文件分割和一次执行。

示例:

Folder and File Structure

   /*************************************************************************************************************************
##NAME   ScriptName.sql
##DESCR  ScriptDescription
*************************************************************************************************************************/

Create table tmp_thm_Test
( tmp_thm_Test_id number(8)
, text varchar2(200));

Create table tmp_thm_Test2
( tmp_thm_Test2_id number(8)
, text varchar2(200));

这是脚本的示例内容。也可以有插入(在字符串中带有&的情况下需要关闭Set Define),更新语句。还要开始/结束脚本。

如果只有DDL和DML语句,我可以拆分它们,但是Begin / End部分不能拆分。一开始我以为我可以像过去一样使用SQL * Plus(@ Scriptname.sql)部署脚本。阅读整个脚本并执行。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

自从我在C#中与Oracle一起工作以来,即使缺乏具体示例,我还是对您有所了解。

SET DEFINE OFF从未在C#中为我工作过,因此我只使用query = query.Replace("'","''");。您还可以使用以下命令参数来避免异常。

        string query = string.Format(
                                    @"UPDATE CardStatus
                                      SET DateExpired = @dateExpired,
                                          ModifiedBy = @modifiedBy,
                                          ModifiedOn = @modifiedOn
                                      WHERE
                                        IDNo = @idNo");

        List<OracleParameter> parameters = new List<OracleParameter>();

        OracleParameter pIdNo = new OracleParameter("idNo", OracleDbType.Varchar2);

        pIdNo.Value = idNo;

        OracleParameter pDateExpired = new OracleParameter("dateExpired", OracleDbType.Date);

        pDateExpired.Value = dateExpired;

        OracleParameter pModifiedBy = new OracleParameter("modifiedBy", OracleDbType.Varchar2);

        pModifiedBy.Value = "SIS";

        OracleParameter pModifiedOn = new OracleParameter("modifiedOn", OracleDbType.Date);

        pModifiedOn.Value = DateTime.Now;

        parameters.Add(pIdNo);
        parameters.Add(pDateExpired);
        parameters.Add(pModifiedBy);
        parameters.Add(pModifiedOn);

        bool result = _DAL.ExecuteNonQuery(query, parameters.ToArray());

_DAL只是我的数据访问帮助类,它管理查询执行,将其放置在单个事务中,以便我决定是提交还是回滚单个到多个查询的更改。

    public bool ExecuteNonQuery(string query, object[] parameters, [CallerMemberName] string callerMemberName = "")
    {
        bool success = false;

        try
        {
            using (OracleCommand command = new OracleCommand())
            {
                command.Connection = _connection;
                command.Transaction = _transaction;
                command.CommandText = query;
                command.CommandType = CommandType.Text;
                command.Parameters.AddRange(parameters);

                command.ExecuteNonQuery();
            }

            this.AuditSQL(query, string.Empty);
            success = true;
        }
        catch (OracleException ex)
        {
            this.AuditSQL(query, ex.Message, callerMemberName);

            if (ex.Number == 54) // SELECT .. FOR UPDATE NOWAIT failed.
            {
                throw new RowLockException();
            }
        }

        return success;
    }

我不确定您是否有兴趣参加我的_DAL课程,但是我为您提供了一段代码,以帮助您了解可以做什么。

编辑:由于您已经提到脚本已经存在,所以它很容易,您只需要确保脚本中没有'字符就可以使oracle请求一个变量值和所有批处理查询必须具有BEGINEND;

示例:

BEGIN

-- INSERT
-- UPDATE
-- INSERT
... etc.

END;

现在,您到底是什么问题?您可以从文件中读取查询,并将所有SET DEFINE OFF(以及您认为不必要的其他语句)替换为string.Empty,并根据需要将所有'替换为''。最坏的情况是,您将使用正则表达式来识别和删除不需要的语句。