공룡호가 사는 세상 이야기

using System;  
using System.Data;  
using System.Data.SqlClient;  
 
public class DB_TEST  
{  
    public static void Main(string[] args)  
    {  
        SqlConnection conn = new SqlConnection();  
        conn.ConnectionString =  
            "Server=ip;database=CL_ADMIN;uid=sa;pwd=password;";  
 
       try 
       {  
          conn.Open();  
          Console.WriteLine("데이터베이스 연결성공..");  
         String log = " SELECT * FROM dbo.OB_TEST"; // 쿼리문  
          SqlCommand cmd = new SqlCommand(log, conn); // 적용  
           SqlDataReader rd = cmd.ExecuteReader(); // 쿼리 수행  
 
          while (rd.Read()) //한줄씩 잃기  
          {  
            Console.WriteLine(String.Format("{0}, {1}", rd[0],rd[1]));  
            //내용 출력하는 부분         
                 
          }  
         rd.Close();  
 
       }  
       catch 
       {  
 
            Console.WriteLine("데이터베이스 연결 실패..");  
        }  
        finally 
        {  
            if (conn != null)  
            {  
                conn.Close();  
            }  
            Console.WriteLine("데이터베이스 연결해제");  
 
        }  
    }  
}

C# TIP 몇가지

프로그래밍2007. 10. 4. 20:34

C#을 해 보면서 기존에 사용하던 언어와 조금 달라서 필요한 것들을 찾아 쓰고 메모해 두었던 것들을 포스팅.

키보드 이벤트 처리

특정 이벤트에서 키보드 키 메시지를 잡아야 할 때, 이벤트 처리 메소드에 전달되는 e 객체의 KeyChar속성을 이용한다. 키보드 각각의 값이 상수로 정의되어 있으므로, 원하는 키의 후킹이 가능
private void NONAME(object sender, System.Windows.Forms.KeyPressEventArgs e)
{
 if(e.KeyChar == (int)Keys.Enter) { ... }
 또는
 if (e.KeyCode.Equals(Keys.Enter))
}

String의 Bytes단위 처리

String에는 영문자가 있을 수도 있고, 특수문자가 있을 수도 있고, 한글이 있을 수도 있다. 총 바이트 개수를 알고 싶을 때에는, 다음과 같이 한다
int length = Encoding.Default.GetByteCount(textBox1.Text);

URL로의 Redirect

LinkLabel을 붙이고, 이벤트에 보면 LinkLabel 클릭 이벤트가 존재한다. 당연히 URL로 이동을 해야 하는데 이런 부분은 속성창에서 지원해 주지 않으므로 직접 코딩한다
System.Diagnostics.Process.Start("http://dolbbi.com");

Dialog를 이용하지 않고 MessageBox의 지원 기능으로 분기하기

사용자의 요구에 따라 특정 이벤트로 분기해야 할 경우, Dialog를 생성하지 않고 MessageBox로 분기한다. 단, 복잡한 분기보다는 Yes/No의 간단한 분기에서 사용. (별거 없다 -_ -)
DialogResult result = MessageBox.Show("choose, yes or no", "messagebox", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Warning);
            switch (result)
            {
                case DialogResult.Yes:
                    // CALL EVENT
                    break;
                case DialogResult.No:
                    // CALL EVENT
                    break;
            }

폴더 및 드라이브를 손쉽게 동기화 해주는 프로그램 입니다.
여차저차, 제가 필요해서 간단히 만들게 되었지만 아직 테스트가 올바로 이루어져 있지 않아,
공개하기에 조금 조심스럽습니다만... 버그를 발견하는 가장 빠른 길이라 여겨져서 이렇게 내놓아 봅니다.
사용법을 굳이 설명해 드리지 않아도 알 수 있을 정도이니 간략하게 마무리 하겠습니다.
동기화 할 원본/대상 폴더 및 드라이브를 설정하고 동기화 시작 버튼을 누르면 동기화가 되는데,
'최근 파일로 동기화'를 선택하면, 두 경로에서 동일한 위치에서 동일한 파일이 발견될 경우,
수정일자가 최근으로 설정되어 있는 파일로 동기화를 실시합니다.
반대로 '확인 후 동기화'를 선택하면, 팝업을 통해 어느 파일로 동기화를 실시할 것인지 묻고,
사용자의 선택에 따라 동적으로 동기화를 실시합니다.


사실, 폴더나 드라이브를 동기화 할 일은 많지 않지요.
하지만, USB메모리 하나 쯤은 누구나 가지고 다니는데, 분실이나 파손 등의 이유로 데이터 손실을 우려하여,
하드디스크 등에 백업을 하게 되는데, 백업을 할 시기를 놓쳐 꽤 오랜 시간 동안 백업을 실시하지 않았고,
USB가 현재 없어서 급한대로 하드디스크에 백업된 데이터를 대상으로 작업을 수행하거나 새로운 파일 등을 추가 했을 때에는 완전히 동일했던 USB와 하드디스크의 백업본조각나기 시작합니다.

이럴 경우에는, 사용자가 일일이 파일을 봐 가면서 어느 것의 파일이 보관되어야 할 파일인지 알아보고,
 손수 작업을 해 주어야 하는 불편함이 있는데, 이 작업을 조금 도와주는 툴이라 생각하면 될 것 같습니다.
 조각난 파일들의 리스트를 모아서 리스트로 보여주고 사용자에게 선택을 하게 해 주니,
 빠트릴 염려도 없고 좀 더 빠르게 동기화가 가능합니다만...
어차피 그 선택은 사람이 하는 것이기 때문에 혹시나 실수로 잘못된 파일을 선택하고 동기화를 진행하는 일에 대해서는 현재 방법이 없습니다.(사용자의 실수까지 커버할 수는 없으니까요)

그래서,
동기화를 진행할 때 마다, 원본 및 대상 데이터들을 일정 공간에다가 백업 해 두고 동기화를 진행하는 방안도,
 생각해 보지 않은 것은 아니나, 동기화 할 데이터들이 굉장히 큰 데이터라면 그 시간은 2배 이상이 될 것이고, 또한 동기화를 진행할 때 마다 백업을 한다면 그 데이터들이 모여 더 큰 데이터들을 만들 우려도 있어
 이 부분은 조금 더 생각을 해 봐서, 보다 간단하게 실수를 보정할 수 있는 기능을 추가할 예정입니다.
(좋은 아이디어 있으신 분은 메일 주시면 감사 드리겠습니다)
라이센스 같은건 당연히(!) 없으므로 아무나 사용하셔도 되고 배포 또한 무방합니다.

닷넷 기반에서 작성 되었으므로,
.NET FrameWork 2.0 이 필요 합니다.
받아서 실행이 되지 않으시는 분들은, 아래 링크에서 dotnetfx.exe를 받아 설치하면 됩니다.
http://download.microsoft.com/download/5/6/7/567758a3-759e-473e-bf8f-52154438565a/dotnetfx.exe

다운 받으시거나, 사용하시는 분들은 꼬리 한번 주시는 센스 -ㅁ-

사용 해 보시는 분들의 버그 레포팅 받겠습니다. 너무 대충 짠 거라, 많은 버그가.. ㅠㅠ

취업을 위해, 자기소개서를 작성하는데 글자 수를 제한하고 있었다.
사실, 영문은 한글에 비해 1바이트 적기 때문에 영문을 많이 쓰는 사람이 좀 더 유리하다.
모 회사에서는 공평하게 하려는 의도인지, 글자 수가 아니라 XXXX바이트로 제한을 두고 있는데,
기껏 노력해서 자기소개서를 완성하고, 입사지원하기 버튼을 눌렀더니 로그아웃이 되었단다.
아놔-_-; 그렇다면 텍스트 에디터에서 알맞게 작성하고 같다 붙여야 한다는 소리가 되는데, 이거 원..
글자 수 세는 프로그램을 검색했더니 바이트 단위를 지원하는 것이 없다.
그냥 간단하게 하나 만들자 싶어서 작성했다.
일전에 친구에게 간단히 배웠던 SmartClient기술을 적용하면, 웹으로도 서비스가 가능하다.


사용자 삽입 이미지

.NET FrameWork 2.0 이 필요하다.
받아서 실행이 되지 않으시는 분들은, 아래 링크에서 dotnetfx.exe를 받아 설치하자.
http://download.microsoft.com/download/5/6/7/567758a3-759e-473e-bf8f-52154438565a/dotnetfx.exe

웹서비스도 가능케 해 두었으니, 프로그램 다운로드가 귀찮으신 분들은
아래 주소로 이동하여 이용하시면 되겠다.
(그러나 웹서비스도 .NET Framework 가 필요하므로 설치는 하셔야 한다는 것 잊지마시길)
http://sera.dongguk.ac.kr/service/charactercounter

다운 받으시거나, 사용하시는 분들은 꼬리 한번 주시는 센스 -ㅁ-

이것 때문에 대체 얼마나 삽질을 해댔는지. 포스트 백만 일어나면 값이 사라졌다.
처음엔 값이 사라지는줄도 몰랐다. FindControl() 메소드도 null만 리턴해댔다.
값이 사라지는 것인지, 컨트롤이 사라지는 것인지 분간도 되지 않았다.

TextBox Property는 내부적으로 작성된 소스를 보게 되면 텍스트의 내용이 null일 경우, string.Empty를 리턴한다.
그래서 참조를 할 경우 참조 에러가 나게 된다.

한가지 더.
패널을 사용하여 각 패널에 컨트롤을 나누어 놓았을 때, Page_Load()의 패널.Visible=false로 설정되면,
페이지가 열릴 때, 해당 패널은 렌더링 되지 않는다.(-_ - 아놔..)
그래서 해당 패널에 동적으로 생성된 컨트롤이 존재 했다면 그 패널 컨테이너 안의 컨트롤은 FindControl()로 찾을 수가 없게 된다.

또 하나 중요한 것은. 웹 폼에서 포스트백 이후에는 변수의 값을 유지할 수가 없다.
그럴때에는 ViewState를 사용해서 값을 유지할 수 있으며, 정적 컨트롤 들은 내부적으로 ViewState를 사용하기 때문에 값이 유지된다. 하지만, 동적으로 생성된 컨트롤의 데이터는 ViewState에 저장이 되지만,
동적인 컨트롤 자체는 ViewState에 저장이 되지 않는다
. 즉 접근할 방법이 없어지므로,
FindControl()은 계속 null을 리턴하고, 접근이라도 할라치면 참조 오류가 나 버린다. 그러니 내가 알 리가 있나..

입력된 값을 가지고 동적으로 TextBox를 생성하고, 생성된 컨트롤로부터 값을 다시 얻어 합을 구한다고 가정.
먼저, 최초에 입력될 값을 보관할 ViewState를 설정한다.
이 설정은, 사용자로부터 값을 입력 받은 다음에 설정한다.

ViewState["TextBoxCount"] = nNumber; // ViewState로 생성된 TextBoxCount에 변수를 저장하여 보관.

다음으로 동적 할당할 TextBox Control을 코딩한 부분을 하나의 함수(메소드)로 묶어서 언제든지 호출 가능한 형태로 구분한다. 여기서는 DrawTextBox() 라고 가정하고, 간단하게 코딩하면 다음과 같다.

private void DrawTextBox()
{
 if(ViewState["TextBoxCount"] != null)               // null이 아니면 값이 할당되었다는 의미
 {
  nNumber = (int)ViewState["TextBoxCount"];     // 캐스팅 하여 본래 값을 복원
  for (int i=1; i<=nNumber; i++)
  {
   Literal li = new Literal();
   li.Text = "<br>" + i + "번째 텍스트 박스 : ";
   Panel2.Controls.Add(li);

   TextBox txt = new TextBox();
   txt.ID = "txt"+i.ToString();
   txt.Width = 80;
   Panel2.Controls.Add(txt);
  }
 }
}

이런식으로 하여 ViewState에 TextBox의 개수를 저장하고,
Page_Load 에서 ViewState 에 값이 있다면 매 페이지마다 다시 컨트롤을 추가해야 한다.

private void Page_Load(object sender, System.EventArgs e)
  {
      DrawTextBox();
  }

그러한 방법으로 TextBox의 값을 유지할 수 있게 된다.
3일동안 삽질했다. 아놔 -_ ㅜ

내 참, 캐스팅 때문에 또 이렇게 시간을 허비하다니.
문법을 다 배우는 게 너무 오랜 시간이 걸린다고 생각해서 간단한 거 하나 만들어 보자는 생각에,
무턱 대고 만들기 시작했는데 생각 외로 많은 문제들에 부딪힌다.
다음은 C#에서의 String Type to Integer Type 캐스팅

int nNumber = Convert.ToInt32(Text1.Text);

ToInt16은 short Type으로 변환되고 ToInt32는 int Type으로, ToInt64는 long Type으로 변환.
다른 Type으로도 변환이 가능한데 Convert의 메소드를 보면 알 수 있다.

주의 할 점이 있다.
String Type에서 Integer Type으로 변환시, 문자열이 정수로 변환할 문자열에 낑겨져 있다면 오류.
변환하기전에 숫자만이 입력 됐는지 체크를 하시던지 아니면 try를 걸어서 예외처리.