GSI

Connection의 이해

Connection은 데이터 저장소와 .NET 응용 프로그램 사이의 물리적 커뮤니케이션을 다른다. Connection 객체는 데이터 공급자의 한 부분이기 때문에. 각각의 데이터 공급자는 자신만의 Connection 객체를 구현한다. .NET 프레임 워크가 제공하는 두 개의 데이터 공급자는 System.Data.OleDB 네임스페이스에서 OleDbconnection을 구현하고, System.Data.SqlClient 네임스페이스에서 SqlConnection을 구현한다.

OleDbConnection은 보통 OLE DB를 사용하는데, Microsoft SQL Server를 포함하여 다른 OLE DB 공급자에서도 사용할 수 있다. SqlConnection 은 OLE DB 공급자를 거치지 않고 직접 SQL Server로 접속하기 때문에, SQL Server일 경우에 효과적이다.


Connection을 직접 생성할 수도 있지만. 여기서는 테스트를 쉽게 하기 위해서
DataAdapter를 사용했다.


OleDbDataAdapter 또는 SqlDataAdapter를 사용해서 공급자를 선택하고 서버명, 로그인 정보를 입력하고 원하는 데이터 베이스를 선택 했다.

그리고 쿼리 생성기를 사용해서 해당 테이블의 컬럼 정보를 선택해서 생성하였다.

이렇게 하면 디자인 뷰의 화면 하단에 oleDbDataAdapter1, oleDbConnection1 또는 sqlDataAdapter1, sqlConnection1 이 생기게 된다.

Connection을 이해 하기 위해서 두개의 ConnectionString를 모두 추가 하였고 이것을 사용해서 테스트를 진행 했다.

두개의 커넥션을 모두 받을수 있는 System.Data.IDbConnection 변수를 하나 생성하였다.
private System.Data.IDbConnection myconnection;

그리고 Ole 또는 Sql 을 선택해서 myconnection에 설정하게 된다.
myconnection = this.oleDbConnection1;

myconnection 은 아래와 같은 3개의 정보를 담고 있다.
1. myconnection.ConnectionString.ToString();
2. myconnection.Database.ToString();
3. myconnection.ConnectionTimeout.ToString();



커넥션을 열고 닫고 하는 과정은 아래와 같다.
this.myconnection.Open();  //커넥션을 오픈한다.
MessageBox.Show(this.myconnection.State.ToString()); //커넥션 상태를 알아본다.
this.myconnection.Close();  //커넥션을 닫는다.


[관련내용]
ConnectionString 속성
ConnectionString은 어느 Connection 객체이든지 간에 가장 중요한 속성이며, 사실상 나머지 속성은 읽기 전용이다. 이들 나머지 속성들은 ConnectionString이 제공한 값에 의해 생성된 Connection에 의해 설정된다.

모든 ConnectionString은 동일한 포멧을 가진다. 그것은 키워드와 값이 한 세트로 구성되고 세미콜론(;)으로 구분되며, 전체가 작은 따옴표나 큰 따옴표로 쌓여 있다.

"keyword=value;keyword=value"

키워드 이름은 대소문자 구별을 하지 않는다. 그러나 데이터 소스에 의존하는 값은 그렇지 않을 수 있다. 작은 따옴표 혹은 큰 따옴표의 사용은 문자열의 기본 규칙을 따른다. 예를 들면, 데이터베이스의 이름이 Becca's Data이면, ConnectionString은 큰 따옴표를 써야 한다. "Database=Becca's Data", 'Database=Becca's Data' 는 에러를 일으킬 것이다.

동일한 키워드를 여러번 사용한다면 마지막 인스턴스가 사용될 것이다. 예를 들어, ConnectionString에 databast=Becca's Data ; database=Northwind"를 준다면, 초기 데이터베이스는 NorthWind가 될 것이다. 다중 인스턴스를 사용하는 것이 구문 에러를 발생하지 않는 가장 이상적인 방법이다.

ConnectionString 형식은 어렵지 않지만, 내용은 데이터 공급자마다 항상 고유하기 때문에 내용을 정의 하는 것이 어려울 수 있다. 그러나 [데이터 연결 속성] 대화 상자를 이용해서 디자인 타임 연결을 생성하고, 그 값을 복사함으로써 쉽게 작업을 할 수 있다.

ConnectionString은 연결이 닫힐 때만 설정할 수 있다. 설정될 때 Connection 객체는 문자열 문법을 검사하고 나머지 속성(앞에서 읽기 전용이고 했던 것을 기억할 것이다)들을 설정할 것이다. ConnectionString은 연결이 열려 있을 때에 완전히 확인할 수 있다. 만약 연결이 확인되지 않거나 제공하지 않는 속성을 발견하면 오류가 발생할 것이다(객체가 사용될 때 의존하고 있는 OleDbException과 SqlDbException 둘 중 하나에서 발생한다.).


이상...
이론 내용은 Microsoft ADO.NET Step by Step 내용 2장에서 발췌 하였음...






Posted by gsi
:

함수가 많을 경우 함수 포인터를 사용해서 배열로 사용하는 방법이 편할때가 있다.

그래서 STL의 vector을 사용해서 함수 포인터 정보를 배열로 저장하고
해당 함수들을 콜해서 처리 하는 방법을 사용할까 한다.


함수 포인터로 사용한 원형을 typedef로 선언한다.

typedef ngevent (*PF)(EVENT_INFO* arg);

이렇게 선언한 후에 일반 포인터로 사용할 경우는 아래와 같이 하면 된다.

PF pf; //pf에 함수 포인터 연결

vector을 사용할 경우에는 아래와 같이 사용한다.

//선언
vector<PF>  m_ClickEventHandler;

//연결할 함수를 작성한다.
ngevent test(EVENT_INFO* arg)
{
 return 1;
}

ngevent test2(EVENT_INFO* arg)
{
 return 1;
}

//vector 함수에 추가
m_ClickEventHandler.push_back(test);
m_ClickEventHandler.push_back(test2);

//함수를 vector의 배열로 for문을 통해서 호출한다.
for(int i = 0; i < (int)m_ClickEventHandler.size(); i++)
{
      EVENT_INFO info;
      info._click2d.x = 10.f * (float)i;
      m_ClickEventHandler[i](&info);
}


//////////////////////////////////////////////////

Posted by gsi
:

함수 포인터 타입 - (펌)

STL 2007. 9. 18. 14:48 |

주소 : http://www.winapi.co.kr/clec/cpp2/15-2-2.htm

함수 포인터 타입도 일종의 고유한 타입이다. 따라서 원형이 다른 함수 포인터끼리는 곧바로 대입할 수 없으며 함수의 인수로도 넘길 수 없다. 정수형 포인터 변수(int *)에 실수형 포인터 변수(double *)의 값을 대입할 수 없듯이 말이다. 다음 코드를 보자.

 

int (*pf1)(char *);

void (*pf2)(double);

pf1=pf2;                  // 타입이 다르므로 에러

 

pf1은 문자형 포인터를 인수로 취하고 정수형을 리턴하는 함수를 가리키는 함수 포인터이며 pf2는 실수를 인수로 취하고 리턴값이 없는 함수를 가리키는 함수 포인터이다. 두 변수가 가리킬 수 있는 함수의 원형이 다르기 때문에 pf2가 가리키는 번지를 pf1에 곧바로 대입할 수 없다. 만약 이것이 가능하다면 pf1로 함수를 호출할 때 컴파일러는 char *형의 인수를 찾지만 pf1이 가리키는 함수는 double형의 인수를 받아들이므로 불일치가 발생하며 함수가 제대로 호출되지 않을 것이다.

함수 포인터가 가리킬 수 있는 원형과 같지 않은 함수의 번지를 대입하는 것도 똑같은 이유로 에러로 처리된다. 다음 코드에서 pf3은 문자형 포인터와 실수를 인수로 취하고 리턴값이 없는 함수를 가리키도록 선언했는데 func 함수는 pf3의 원형과 다르므로 pf3에 func 함수의 번지를 대입할 수 없다.

 

int func(int a);

 

void (*pf3)(char *, double);

pf3=func;                         // 에러

 

그러나 타입이 다른 함수 포인터끼리라도 강제로 대입할 수는 있는데 이것이 일단은 가능해야 한다. void 포인터에 저장된 함수의 번지를 대입받는다거나 자료 구조 설계시에 미리 알 수 없는 함수에 대한 포인터를 다루고자 할 때이다. 이럴 때 사용하는 것이 바로 캐스트 연산자이며 여러 가지 이유로 강제 캐스팅의 필요성은 누구나 인정하고 있다. int *pi와 double *pd가 있을 때 pi=pd 대입은 금지되지만 pi=(int *)pd는 가능한 것처럼 함수 포인터도 타입에 맞게 캐스팅하면 강제로 대입할 수 있다.

데이터 포인터에서와 마찬가지로 함수 포인터에도 캐스트 연산자를 쓸 수 있는데 문제는 함수 포인터의 캐스트 연산자가 모양이 생소해서 조금 어렵다는 것이다. 함수 포인터는 타입 자체가 길기 때문에 캐스트 연산자의 모양도 상당히 복잡해 보인다. 다음 코드는 pf2를 pf1에 강제로 대입하기 위해 캐스트 연산자를 사용한 것이다.

 

int (*pf1)(char *);

void (*pf2)(double);

pf1=(int (*)(char *))pf2;

 

이 식에서 (int (*)(char *))가 캐스트 연산자이다. 함수 포인터형의 캐스트 연산자를 만드는 방법은 함수 포인터 선언식에서 변수명을 빼고 전체를 괄호로 한 번 더 싸주면 된다. 일종의 공식이므로 외워 두거나 아니면 필요할 때마다 이 공식을 찾아보기 바란다.

pf1=(int (*)(char *))pf2 대입문은 pf2가 가리키는 번지를 문자형 포인터를 인수로 취하고 정수를 리턴하는 함수 포인터 타입으로 잠시 바꾼 후 pf1에 대입한다. pf3에 func 함수의 번지를 강제로 대입할 때도 마찬가지로 캐스트 연산자를 사용할 수 있다. 물론 이렇게 강제로 대입했을 때의 부작용에 대해서는 스스로 책임져야 한다.

 

pf3=(void (*)(char *,double))func;

 

캐스트 연산자가 길어 보여서 그렇지 원리를 알고 나면 별로 어렵지 않다. 다음은 조금 이론적인 얘기가 되겠지만 함수 포인터의 배열이나 포인터를 선언하는 형식에 대해 알아보자. T형에 대해 T형 배열과 T형 포인터를 항상 선언할 수 있으므로 함수 포인터에 대해서도 배열과 포인터를 선언할 수 있다. func 타입의 함수를 가리킬 수 있는 함수 포인터를 요소로 가지는 크기 5의 arpf 배열은 다음과 같이 선언한다.

 

int (*arpf[5])(int);

 

함수 포인터 배열을 선언할 때는 변수명 다음에 첨자 크기를 밝혀 주면 된다. 잘못 생각하면 int (*arpf)(int)[5];가 맞을 것 같기도 한데 첨자 크기는 반드시 변수명 다음에 바로 써야 한다. 이 선언에 의해 int (*)(int)형의 함수의 번지를 가리킬 수 있는 함수 포인터 arpf[0] ~ arpf[4]까지 4개의 변수가 생성되며 각 변수는 int func(int)와 같은 원형의 함수를 가리키는 번지를 가질 수 있다. 동일한 타입의 변수들을 배열에 모아 두면 루프를 돌면서 함수들을 순서대로 호출한다거나 하는 처리도 가능해진다.

다음은 함수 포인터의 포인터를 선언해 보자. func 타입의 함수를 가리키는 함수 포인터를 가리키는 포인터 ppf는 다음과 같이 선언하는데 * 구두점만 하나 더 적으면 된다.

 

int (**ppf)(int);

 

이렇게 선언된 ppf는 int (*)(int) 타입으로 선언된 함수 포인터 변수나 함수 포인터 배열을 가리킬 수 있는 이차 함수 포인터 변수이다. ppf=&pf 또는 ppf=arpf 식으로 함수 포인터 변수의 번지를 대입받을 수 있으며 ppf로부터 함수를 호출할 때는 (**ppf)(2) 형식을 사용한다. 함수 포인터 배열 arpf와 이중 함수 포인터 ppf가 메모리에 구현된 모양은 다음과 같다.

함수 포인터의 타입은 함수가 취하는 인수들의 타입과 리턴값까지 정확하게 밝혀야 하기 때문에 타입의 형식이 너무 길어서 쓰기에 번거롭다. 또한 함수 포인터로부터 파생된 타입을 만드는 것도 헷갈리고 생소한 면이 있다. 그래서 함수 포인터 타입을 자주 사용하거나 자신이 없다면 직접 타입을 기술하는 것보다 typedef로 함수 포인터 타입을 따로 정의한 후 사용하는 것이 편리하다. int func(int)형의 함수를 가리키는 타입은 다음과 같이 정의한다.

 

typedef int (*PFTYPE)(int);

PFTYPE pf;

 

함수 포인터를 선언하는 문장에서 변수명을 원하는 타입 이름으로 바꾸고 앞에 typedef만 붙이면 된다. 이후 컴파일러는 PFTYPE이라는 명칭을 int (*)(int) 타입으로 인식하므로 PFTYPE으로 함수 포인터 변수를 쉽게 선언할 수 있으며 캐스트 연산자로도 사용할 수 있다. 또한 함수 포인터로부터 배열이나 포인터같은 파생 변수를 선언하는 것도 훨씬 더 간편하다.

 

PFTYPE arpf[5];

PFTYPE *ppf;

 

마치 int형으로부터 배열이나 포인터를 선언하듯이 PFTYPE을 사용할 수 있으므로 직관적이고 읽기에도 좋다.

Posted by gsi
:

회사 컴퓨터에 sql 2000을 깔았다.
DB를 배우다 보니 2005 이상의 좋은 환경에서의 공부는 몬가 부족하다.
세부적인 내용을 알지 못하고 DB를 편하게만질수 있는것과, XML과의 통합으로 인해서
몬가 편해진듯 보이면서도 확장하기 위한 기본 기술이 너무 부족한듯 하다.

Visual Studio 2003을 기준으로 해서 ADO.NET를 기본을 조금더 배우고
작업에 들어가야 할거 같다.
Posted by gsi
:

STL 샘플 코드...강추!!!

STL 2007. 9. 18. 10:30 |

Posted by gsi
: