通过存储过程进行Oracle批量插入。花太多时间

时间:2012-02-13 11:33:49

标签: c# .net oracle stored-procedures plsql

我尝试从c#代码到oracle数据库有效地进行批量插入/更新。 如果我通过声明完成它,那么它不会花费太多时间。

我正在使用ODP.NET 目前通过以下存储过程插入6000条记录需要15分钟。 我必须使用这个存储过程,因为它生成唯一的user_id。

这个proc是自动提交吗?我应该关闭任何自动提交设置吗?

请提出有效方法。

 CREATE OR REPLACE
PROCEDURE sbx_staging_insert_user(client       IN varchar2,
                    username     IN varchar2,
                    comm_type    IN varchar2,
                    email_addr   IN varchar2,
                    buddy_name   IN varchar2,
                    --default_flag IN char,
                    user_id      OUT INT)

AS
BEGIN
select sbx_staging_user_id_seq.nextval into user_id from dual;
insert into sbx_staging_user
  (user_id,
   client,
   username,
   comm_type,
   email_addr,
   buddy_name,
   default_flag)
values
  (user_id,
   client,
   username,
   comm_type,
   email_addr,
   buddy_name,
  'Y');
   end sbx_staging_insert_user;

和C#代码是:

  cmd.Transaction = conn.BeginTransaction();

                        cmd.CommandType = CommandType.Text;

                        cmd.CommandText = "sbx_staging_insert_user";
                        cmd.CommandType = CommandType.StoredProcedure;

                        var userClientParam = new OracleParameter(":client", OracleDbType.Varchar2);
                        var usernameParam = new OracleParameter(":username", OracleDbType.Varchar2);
                        var commTypeParam = new OracleParameter(":comm_type", OracleDbType.Varchar2);
                        var defaultParam = new OracleParameter(":default_flag", OracleDbType.Char) { Size = 1};
                        var emailParam = new OracleParameter(":email_addr", OracleDbType.Varchar2) { IsNullable = true };
                        var buddyParam = new OracleParameter(":buddy_name", OracleDbType.Varchar2) { IsNullable = true };
                        var userIdParam = new OracleParameter(":user_id", OracleDbType.Int32) { Direction = ParameterDirection.Output };

                        cmd.Parameters.Add(userClientParam);
                        cmd.Parameters.Add(usernameParam);
                        cmd.Parameters.Add(commTypeParam);
                        //cmd.Parameters.Add(defaultParam);
                        cmd.Parameters.Add(emailParam);
                        cmd.Parameters.Add(buddyParam);
                        cmd.Parameters.Add(userIdParam);

                        var cuList = new List<string>(Users.Count);
                        var uList = new List<string>(Users.Count);
                        var ctList = new List<string>(Users.Count);
                        var dfList = new List<char>(Users.Count);
                        var eaList = new List<string>(Users.Count);
                        var bnList = new List<string>(Users.Count);
                        var uiList = new List<decimal>(Users.Count);

                        int loopCnt = 0;
                        foreach (var ud in Users)
                        {
                            cuList.Add(ud.User.Client);
                            uList.Add(ud.User.Username);
                            ctList.Add(ud.User.CommType);
                            dfList.Add(ud.User.Default ? 'Y' : 'N');
                            eaList.Add(ud.User.Email);
                            bnList.Add(ud.User.BuddyName);

                            uiList.Add(-1);
                        }

                        userClientParam.Value = cuList.ToArray();
                        usernameParam.Value = uList.ToArray();
                        commTypeParam.Value = ctList.ToArray();
                        //defaultParam.Value = dfList.ToArray();
                        emailParam.Value = eaList.ToArray();
                        buddyParam.Value = bnList.ToArray();
                        userIdParam.Value = uiList.ToArray();

                        cmd.ArrayBindCount = cuList.Count;//Users.Count;//
                        cmd.ExecuteNonQuery();
                        cmd.Transaction.Commit();

2 个答案:

答案 0 :(得分:0)

尝试这样的事情(未经测试的,为简洁而缩短):

public void insertRows()
{
 if (Users.Count > 0)
 {
  OracleTransaction trans=_conn.BeginTransaction();
  try
  {
   // create insert statement with bind vars
   Stringbuilder sb = new Stringbuilder();
   sb.Append("INSERT into sbx_staging_user(");
   sb.Append("client,");
   sb.Append("username,");
   sb.Append("user_id");
   sb.Append(") VALUES (");
   sb.Append(":client,");
   sb.Append(":username,");
   sb.Append("seq_user_id.nextval");
   sb.Append(") ");

   OracleCommand cmd = new OracleCommand(sb.ToString(), _conn);

   string[] ary_client = new string[Users.Count];
   string[] ary_username = new string[Users.Count];

   for (int i=0; i<Users.Count; i++)
   {
    User row=Users[i];
    ary_client[i]=row.client;
    ary_username[i]=row.username;
   }
   // prepare bind vars(bind in bulk using arrays)
   OracleParameter prm=new OracleParameter();
   cmd.Parameters.Clear();
   cmd.ArrayBindCount=Users.Count;
   cmd.BindByName=true;

   prm=new OracleParameter("client", OracleDbType.Varchar2); prm.Value=ary_client; cmd.Parameters.Add(prm);
   prm=new OracleParameter("username", OracleDbType.Varchar2); prm.Value=ary_username; cmd.Parameters.Add(prm);

   cmd.ExecuteNonQuery();
   trans.Commit();
   trans.Dispose();
  }
  catch {
   trans.Rollback();
   trans.Dispose();
   throw;
  }
 }
}

答案 1 :(得分:0)

也许你应该将批量逻辑移到pl sql 请看这里的例子:
http://dotnetslackers.com/articles/ado_net/BulkOperationsUsingOracleDataProviderForNETODPNET.aspx