C#에서
using System.Data.OracleClient;
을 선언하여 데이터를 select하여 DataTable에 담던중... 오류가 나서 보니
null값에 대한 처리가 안되서 그랬다.

테이블예제
 SEQ  TITLE  주소
 1  제목입니다.  http://xxx.xxx/xxxx
 2  null  http://yyyy.yyy/yyyyy
 3  뇌이벌  http://zzzz.zzz/zzzz


처음에는 reader.GetString(1) == null 로 체크하면 될줄 알았으나... 그것은 아니었다. (모르는게 죄다 ;;;)
reader.IsDBNull(2) 같이 null인지 체크하는 기능이 있으니 체크를 해야했다.

[기존코드형식]
                while (reader.Read())
                {
                    row = table.NewRow();
                    row["SEQ"] = string.Format("{0}", reader.GetInt32(0));
                    row["TITLE"] = (string)reader.GetString(1);                             // <------ 요놈이 문제 (null데이터가 존재해서)
                    row["URL"] =    (string)reader.GetString(2)
                    table.Rows.Add(row);
                }


[해결방법]
 while (reader.Read())
                {
                    row = table.NewRow();
                    row["SEQ"]    = string.Format("{0}", reader.GetInt32(0));
                    row["TITLE"] =  getString(reader, 1, "제목없음");                             // <------ 요놈이 문제 (null데이터가 존재해서)
                    row["URL"]    =  getString(reader, 2, "");                                         //              그래서 null체크하는 함수를 편의상만듬
                    table.Rows.Add(row);
                }


.... 생략....

        // db널체크를 하는 함수를 만들자!!!
        private static string getString(OracleDataReader reader, int idx, string defaultstr)
        {
  //널체크
            if (reader == null)
                return defaultstr;

            if (reader.IsDBNull(idx) == true)                    // <---- DB값 null체크
                return defaultstr;
            else
                return reader.GetString(idx);
        }


뭐 일단 나의 착오였으나 까먹지 않게...정리..

참고로 Get관련 메소드에서 GetOraclexxx 형태로 가져올수도 있는데,
이 경우에서 null체크하기가 좀더 편하다 메소드가 따로 있는 구조가 아니라

reader.GetOracleString(1).Value
reader.GetOracleString(1).IsNull

같이 동일한 호출에서 .Value냐 IsNull이냐가 가능해서 좀더 편하게 쓸수 있을듯....








각의 언어별로 나름대로 디자인과 로직을 나누는 노력을 하기는 하지만...
그래봤자 페이지(파일)에 종속되어 있다는 생각을 가진건 언제 부터일까?
참고로 직업 특성상  jsp, .net, php, asp 할 거 없이 다양한 언어와 환경을 접하고 비슷한걸 반복하는 느낌이다


웹언어에서는 html코드라는 디자인과, 데이터를 처리하는 로직을 나누려는 노력이 많이 있어왔다.
.NET(C#)을 쓴다면 .aspx라는 디자인파일과 .cs라는 로직용 파일이 따로 존재하는것 처럼
둘을 분리하였고, 실제로 구현하다보면 기존 형식처럼 하나의 파일로 구현하는 것보다  코드 읽기가 좋아진것도 사실이다.


질문 : "A라는 사이트를 구축했는데, B사이트에서 그걸 그대로 활용해서 쓰고 싶어요..."

아무리 A사이트가 디자인과 로직을 분리하여 개발했다고 해도...
B사이트에서 A사이트의 로직코드만으로 처리를 할 수 없다.

답변 : "OPEN-API(xml)형태로 제공하면 됩니다"


그래서 요즘들어 많이 눈에 보이는게 OPEN-API 라는 용어가 나돌기 시작했고,
요즘 많이 사용하는 XML이라는 형식에 맞춰 오브젝트(Object)가 아닌 메시지(Message)를 주고 받는다는것이다.
(Object라면 프로그래밍 언어에서 사용하는 Array, String 같은 변수같은걸 의미하고,
 Message라는건 사람이 눈으로 보고 읽을수 text를 말한다..물론 여기서는 xml을 말함)




<A> Object전달 방식의 로직과 디자인 분리
기존에서의 로직디자인을 분리하는건... (Object로 전달받는 형식)
   1. 로직에서는 가공된 최종 값(Value)을 뽑고,                            <--- 즉, array, string, int 같은 데이터 이므로 printf하기전엔 못봄
   2. 디자인에서는 그 값(Value)에 디자인을 입히는 작업이었다

<B> Message전달 방식의 로직과 디자인 분리
최근 든 나의 생각은  로직디자인으로 분리하는건 (Message를 전달 형식)
   1. 로직에서는 가공된 최종 값(Value)을 뽑아, 결과를 Message로 출력한다.       <--- 즉, 내 눈으로 볼수 있는 text가 존재한다
   2. 디자인에서는 그 Message에 디자인을 입힌다.

A와 B의 큰 차이점은
B에서는 1번만 처리되도 사람이 확인할 수 있는 "눈에 보이는 결과(Message)" 가 있다는것이다.

어찌보면
==>   B의 1번  = A번의 1번 + (최소의 디자인) A번의 2번
이라는 공식이 될지도 모르겠다.



내가 말하고자 하는 차이점은
<A>object -> 디자인적용

<B>object -> message -> (메시지파싱,xml파싱)  object -> 디자인적용


라는 단계가 되고,
<B>에서는 (파싱하는)중간단계가 생성되어 시간이 더 소요되겠지만...
의미있는 점은 message(예: xml) 는 다시 object로 바꿀수 있다는 것이다.

내생각으로는 어찌보면 진정한 로직과 디자인적인 분리가 아닐까?
하는 생각이 문득 든다.

message로 주고 받는건 웹서비스에서도 나온 개념이고...
웹개발도 이런 느낌으로 바뀌는게 맞지 않나? 싶기도하다.



Ps.
뭔가 머릿속에는 지금 뭔가 맴도는걸... 딴사람에게 전달하려고 했는데 마음만 앞서서
쉽게 풀어 쓰지 못한거 같은느낌 ;;;;;;



보통 부서의 상위 관계추적을 할 때 사용한다.
상위 하위 관계가 존재하는 트리구조와 같은 형태에서 필요한 구조라고 할까?

TB_DEPT

 부서코드 (dept_code)  부서명(dept_name)  상위부서코드(parent_dept_code)
 A  무지좋은 회사  
 B  그저그런 부서  A
 C  최악의 팀  B


TB_USER
 이름 (NAME)  부서코드 (DEPT_CODE)
 홍길동  C
 둘리  B
 사장님  A

와 같은 테이블이 있다고 했을때,
하위부서코드 하나로 관계된 상위 부서코드까지 뽑아내는것이 필요하다.
즉, C라는 부서코드를 넣으면 C-B-A 같은 값을 뽑아내야 하는 상황이라는 것...


즉,
SELECT NAME, DEPT_CODE, dbo.FN_TAR_DEPT(DEPT_CODE,'','-') AS FULL_DEPTCODE FROM TB_USER
의 결과는 요렇게

 NAME  DEPT_CODE  FULL_DEPTCODE
 홍길동  C  C-B-A
 둘리  B  B-A
 사장님  A  A

/**********************************************
* 하위 코드와 상위코드값으로 전체 코드값을 가져옴
*  arg -----------------------------------------
*  @pkey         == 내 자신의 키
*  @outputtmp  == 초반에 시작할 값 (재귀에서는 값전달용)
*  @  del          == 구분자
*
*  output -------------------------------------
*  예 : FN_TAR_DEPT('C', '', '-')
*  결과 C-B-A
*
* MAKE BY 정민철 (MSSQL용)
***********************************************/

CREATE FUNCTION FN_TAR_DEPT(@pkey varchar(50), @outputtmp varchar(1000), @del varchar(2)) RETURNS varchar(1000) AS
BEGIN
            --상위 코드값을 가져옴
             DECLARE curTab CURSOR FOR
                SELECT top 1 tb_dept.parent_dept_code FROM tb_dept WHERE deptcode = @pkey
             OPEN curTab
            
             DECLARE @output varchar(1000)
             DECLARE @par_dept varchar(50)
             SET @output = ''
             SET @par_dept = ''
            
             FETCH NEXT FROM curTab INTO @par_dept
            
             IF @@FETCH_STATUS = 0
              BEGIN
                   IF @pkey  = ''   -- 재귀의 종료조건(ROOT의 부모코드는 '' 임)
                    BEGIN
                      return @outputtmp
                    END
                  ELSE
                   BEGIN             -- 값있으면 상위코드를 추적(재귀)
                      SET @output = dbo.FN_TAR_DEPT(@par_dept,@outputtmp,@del)
                   END
                    
                   -- [시작] 결과값을 묶어줌 (TAR) --
                   IF @output  = ''
                    BEGIN
                      SET @output = @pkey
                    END
                   ELSE
                    BEGIN
                      SET @output = @output + @del  + @pkey
                    END
                   -- [끝] 결과값을 묶어줌 (TAR) --
              END
        
           CLOSE curTab
           DEALLOCATE curTab
          
           return @output
END







 

+ Recent posts