출처 : http://blog.naver.com/lcg2004?Redirect=Log&logNo=60049785458

참고 : http://www.devpia.com/MAEUL/Contents/Detail.aspx?BoardID=17&MAEULNo=8&no=117409&ref=117385

Writing to Oracle CLOB fields
using System.Data.OracleClient

만약 당신이 .NET 코더고 오라클을 갖다가 데이터베이스 작업을 한다면, 이번이 적절하게 사용할 수 있는 기회가 될 것이다.^^ 읽으면서 커멘트도 달아주기 바란다!

우리 현재 프로젝트에서 우리는 ASP.NET 1.1 애플리케이션으로부터 상당한 량의 텍스트를 오라클 CLOB 필드로 쓸 필요가 있다. 우리는 이제껏 표준 MS System.Data.OracleClient 라이브러리를 (더 작은 량의 데이터를 쓰기위해) 사용해왔고, 그것은 우리에게 아주 유용했다. 나는 오라클 ODP.NET과 같은 더 최신버전의 우수한 팩이 있더라도 다른 라이브러리 팩을 소개하고 싶지 않았다.

예전의 자바 프로젝트에서 나는 CLOB를 쓰고 읽는 작업을 해왔고, 또한 나는 당신이 일반 VARCHAR과 같은 필드를 핸들해야 했다는 것을 안다.

따라서 나는 자리잡고 앉아서 .NET 동적Help과 가능하다면 가능한 모든 인터넷을 뒤지기 시작했고, 그 결과 흥미로운 것이 있었고, 나는 세가지 각각 다른 방법을 발견했다. 두가지는 정말로 단순하고 하나는 그리 단순하지 않다. 희안한 것은 내가 두 옵션은 제대로 작동할 것이라고 생각하지 않고-그러나 내가 테스트 했을 때 제대로 작동했다.
나는 3가지 방법을 여기서 공개할 것이다. 그리고 바라건데 .NET과 Oracle로 지가 머하는가를 아는 누군가는 나를 불꽃으로 격추시킬 수 있길 바란다.(청출어람하길 바란다..)

이것을 테스트 하기위해, 나는 오라클에다가 단순한 테이블을 생성하고, 그 테이블은 2개의 필드로 구성되어있다; ID(INT)와 TEXT(CLOB). 바로 그거다. 나는 노트패드로 생성된 단순 텍스트 파일을 읽을 것이며, 그것은 499KB다.

주: 이것은 테스트코드일 뿐, 당신이 실무에서 하고 싶은 것과는 별개이다. 만약 이코드를 사용하고 싶다면, 적절한 에러나 예외, 핸들링 등을 추가하라.

그래서, OracleDataAdapter를 이용하는 첫번째 방법은 안돌아 갈 것이다.(내가 클래스 라이브러리 문서들을 이해한 기준에서는..). 그러나, 맞긴맞다.

public void writeDataWithDA()

{

           FileInfo fi = new FileInfo("c:/temp/testfile.txt");

           StreamReader sr = new StreamReader(fi.FullName);

           String clob = sr.ReadToEnd();

           sr.Close();

 

           OracleDataAdapter da = new OracleDataAdapter(

               "SELECT ID, TEXT FROM CLOBTEST", ConnectionString);

           DataTable dt = new DataTable();

           // get the schema

           da.FillSchema(dt, SchemaType.Source);

 

           OracleCommandBuilder cb = new OracleCommandBuilder(da);

 

           int id = 2;

 

           // create a row containing the data

           DataRow row = dt.NewRow();

           row["ID"] = id;

           row["TEXT"] = clob;

           dt.Rows.Add(row);

 

           // update the table

           da.Update(dt);

}

두번째 방법은 OracleCommand 를 이용하는 것이며, 이것도 안돌아간다(내 생각엔). 근데 원래는 되는 방법이다.

public void writeDataWithCommand()

{

           FileInfo fi = new FileInfo("c:/temp/testfile.txt");

           StreamReader sr = new StreamReader(fi.FullName);

           String tempBuff = sr.ReadToEnd();

           sr.Close();

           

           using(OracleConnection conn = new OracleConnection(ConnectionString))

           {

                      conn.Open();

                      Console.WriteLine("Connected...") ;

                      String strSQL = 

                          "INSERT INTO CLOBTEST (ID,TEXT) VALUES (1,:TEXT_DATA) ";

 

                      OracleParameter parmData = new OracleParameter();

                      parmData.Direction = ParameterDirection.Input;

                      parmData.OracleType = OracleType.Clob;

                      parmData.ParameterName = "TEXT_DATA";

                      parmData.Value = tempBuff;

 

                      OracleCommand cm = new OracleCommand();

                      cm.Connection = conn;

                      cm.Parameters.Add(parmData);

                      cm.CommandText = strSQL;

                      cm.ExecuteNonQuery();

 

                      conn.Close();

           }

 

           Console.WriteLine("Done!") ;

}

이제 세번째 방법이다. 이것은 .NET 클래스 라이브러리 문서가 기술한 C/BLOB 핸들링 방법이며, 임시 LOB 객체를 오라클에 생성한 다음, insert작업을 하기전에, 그 객체를 쓰므로써 핸들링하는 방법이다. 이것은 역시나 잘돌아간다, 근데 이 방법은 트랜젝션과 다른 부분간에 약간 더 많은 혼란을 겪어야 한다.

public void writeWithTempBlob()

{

           FileInfo fi = new FileInfo("c:/temp/testfile.txt");

           StreamReader sr = new StreamReader(fi.FullName);

           String tempBuff = sr.ReadToEnd();

           sr.Close();

 

           using(OracleConnection conn = new OracleConnection(ConnectionString))

           {

                      conn.Open();

                      Console.WriteLine("Connected...") ;

                      OracleTransaction tx = conn.BeginTransaction();

 

                      OracleCommand tempcmd = conn.CreateCommand();

                      tempcmd.Transaction = tx;

                      tempcmd.CommandText = "declare xx clob; begin dbms_lob.createtemporary(xx, false, 0); :tempclob := xx; end;";

                      tempcmd.Parameters.Add(new OracleParameter("tempclob",

                                 OracleType.Clob)).Direction = ParameterDirection.Output;

                      tempcmd.ExecuteNonQuery();

 

                      //get the temp lob object

                      OracleLob tempLob = (OracleLob)tempcmd.Parameters[0].Value;

 

                      //transform into byte array

                      System.Text.Encoding enc = Encoding.Unicode;

                     //MUST be unicode encoded!

 

                      Byte[] b = enc.GetBytes(tempBuff);

 

                      tempLob.BeginBatch(OracleLobOpenMode.ReadWrite);

                      tempLob.Write(b,0,b.Length);

                      tempLob.EndBatch();

 

                      OracleCommand cmd = conn.CreateCommand();

                      cmd.Transaction = tx;

                      cmd.CommandText = 

                          "INSERT INTO CLOBTEST (ID, TEXT) VALUES (:ID, :TEXT)";

                      cmd.Parameters.Add("ID", 3);

                      cmd.Parameters.Add("TEXT", OracleType.Clob).Value = tempLob;

                      //insert the temp lob

 

                      cmd.ExecuteNonQuery();

 

                      tx.Commit(); 

           }

           Console.WriteLine("Done!") ;

}

임시 CLOB에 write할려면 텍스트는 유니코드여야 한다. 안그러면 당신은 완전 많은 문자들이 쓰여진 것을 경험하게 될 것이니 주의하라.^^

다른 참고자료

+ Recent posts