닷넷프로그래밍정복 김상형저 가메출판사

 

닷넷은 데이터베이스 클라이언트 제작을 훌륭히 지원한다. 응용프로그램 작성을 위한 풍북하고 강력한 언어적 지원은 물론이고 DB접속 라이브러리까지 포함되어 있어 별도의 외부 라이브러리 없이도 자체적인 개발이 가능하다. 개발 툴의 지원도 막강하여 마법사와 각종 코드 생성 툴을 통해 최소한의 의사표현만으로도 자동화된 처리가 가능하다. 심지어 DB 성성이나 테이블 관리 등 설계와 테스트를 위한 서버의 기능까지도 일부 포함하고 있어 그야말로 DB응용프로그램제작을 위한 최적화된 툴이다.

 

 

 

특징

ADO(ActiveX Data Objects)는 MS가 COM프로토콜 기반ㅇ에 메일이나 파일 시스템 등 비 관계형 데이터에도 접속할수 있는 OLE DB를 사용하기 위해 래핑한 것이다.

ADO는 서버와의 연결을 항상 유지한태로 동작했는데 이런 방식을 연결형이라고 한다. 연결형은 서버에 연결된 상태에서 필요한 SQL문을 실행하거나 저장 프로시서를 직접적으로 호출하는 방식이다. 클라이언트는 사용자의 요청만 처리하며 데이터 관리는 서버에게 전달하여 서버가 모든 것을 처리한다. 클라리언트는 데이터 처리를 요청하고 서버는 요청에 응답한다.

ADO 장점

모든 데이터를 서버가 관리함으로써 클라이언트의 메모리 사용량이 적고 별다른 준비를 할 필요가 없으므로 기동속도가 빠르다. 필요할때만 명령을 보내므로 오버헤드가 적은 편이다. 서버가 할수 있는 모든 요청을 다 보낼수 있는 섬세한 데이타 조작이 가능하며 심지어 새로운 DB개체를 새애성하는 DDL명령까지도 수행가능하다. 항상 연결된 상태에서 서버의 실시간 정ㅂ조를 참조하므로 현재성도 높다.

ADO 단점

다수의 클라이언트가 동시에 요청을 보내면 서버의 부담이 증가한다는 점이 가장 큰 문제점이다. 데이터를 출력할때마다 서버의 데이터를 매번 읽어야 하며 반복적인 작업을 할 경우 네트워크 트래픽이 과다해져 전체적인 속도가 떨어지고 반응성도 나빠진다. 다수의 동시 사용자를 무리 없이 지원하려면 서버의 하드웨어 사양이나 네트워크 장비가 엄청나게 고성능이어야 한다. 또 대부분의 DBMS는 연결되는 클라리언트 수에 따라 라이선스 비용을 매기므로 연결이 많아지면 전체적인 비용이 기하급수적으로 증가한다.

 

ADO.NET은 기존의 연결형 외에 서버와의 연결이 끊어진 채로 동작할수 있는 비연결형을 추가로 지원한다. 비연결형은 연결을 하기는 하되 필요한 데이터만 잽싸게 가져오고 연결을 끊어버리는 방식이다. 최초 연결시 서버의 데이터에 대한 사본을 작성하며 오프라인에서 사본을 조작한 후 결과를 서버로 보낼 때만 다시 연결한다. 여기서 비연결이란 아예 연결을 하지 않는 것이 아니라 꼭 필요할 때만 잠시 연결한다는 뜻이다. 서버의 데이터를 가져온 클라이언트가 혼자서 북치고 장구친다는 뜻이다. 서버는 데이터 저장 역할만 하면 되므로 무엇보다 서버에 부담이 적어서 훨씬 더 많은 동시 사용자를 지원할수 있다는 것이 장점이다.

 

비연결형의 핵심은 메모리에 구축된 DB인 DataSet 클래스이다. DataSet은 관계형 데이터베이스 하나에 대응되는 메모리 상의 오프라인 DB라고 할수 있는데 연결이 끊어진 동안 서버의 역할을 대신한다. 여러개의 테이블에 대해 동시에 작업할수 있고 다른 소스로부터 온 테이블도 같이 조작할수 있다. 이 기종 DBMS에서 가져온 데이터나 심지어 관계형이 아닌 데이터도 하나의 데이터 집합에 몰수 있다. 테이블들을 클래스화 하여 쉽게 사용할수 있을뿐 아니라 타입체크가 엄격해 오류 가능성도 낮다. 정적인 사본이므로 컨트롤에 바인딩하기도 편리한데 컨트롤과 연결해 놓으면 데이터 집합의 내용이 콘트롤에 나타나고 콘트롤을 편집하면 데이터 집합이 즉시 수정된다. 메모리에 완전한 사본을 가지고 있으므로 자유로운 랜덤 억세스가 가능하여 억세스 속도는 환상적이다. 반복적인 작업을 해도 속도 상의 불이익이 거의 없다.

단점은 대량의 데이터를 메모리에 계속 보유해야 하므로 클라이언트가 엄청난 리소스를 소모한다. DB의 용령은 적어도 10메가정도는 되며 클 경우 수백메가를  육박하기도 하는데 이 거대한 데이타의 크기만큼 메모리가 요구된다. 일단 가져오면 빠른속도로 억세스 할수 있지만 가져오는 시간이 오래 걸리므로 기동속도가 느리다. 서버에서 가져온 사본만을 조작하므로 새로운 개체를 생성하는 DDL명령은 수행할수 없으며 실시간으로 저사되는 정보가 아니므로 연결형에 비해 현재성도 떨어진다.

 

구조

ADO.NET은 DBMS에 독립적인 접속환경을 제공하는데 그 핵심은 공급자(Provider)이다. 공급자는 DB에 연결하고 명령을 실행하는 모듈로서 응용프로그램에게 DBMS의 데이터를 공급하는 역할을 한다. DBMS별로 공급자가 제공되며 응용프로그램은 공급자를 통해 DBMS에 연결하고 SQL명령을 실행한다. 공급자의 개념은 윈도우즈의 디바이스 드라이버와 개념이 유사하다. 그래픽 카드가 바뀌면 디바이스 드라이버만 바꾸면 될뿐 응용프로그램을 다시 컴파일할필요가 없다. 연결해보자면 각 DBMS는 그래픽카드가 될 것이고 ADO.NET은 장치관리자, 공급자는  드라이버에 해당한다.

공급자중에 가장 성능이 좋고 신뢰성이 높은 것은 SQL서버이며 닷넷과 가장 잘 어울린다.

 

 

테이블

마법사로 만든 코드들은 이런 맹점이 있다

  • 마법사로 코드를 만들기는 쉽지만 거꾸로 되돌리기는 어렵다. 직접 작성한 코드는 그냥 지우면 되지만 마법사가 만든 코드를 함부로 편집하면 잘 되던 것도 안된다
  • 익숙해지는데 많은 시간이 걸린다. 코드는 보고 따라하면 되고 잘 안될 경우 레퍼런스라는 친절한 안내자가 있지만 마법사는 조작순서를 일일이 외워야 하며 문서를 통해 참조하기 어렵다
  • 생각보다 버그가 많고 완성도가 떨어져 원하는대로 동작하지 않는 경우가 허다하다. 원하는 모든 동작을 마법사로 다 처리할수 없으며 결국은 손으로 직접마무리 해야 한다
  • 애쎄 배워봤자 버전이 바뀌면 왕창 달라져 지식으로서의 가치가 없다. 반면 코드는 하위호환성을 철저하게 유히되므로 애쌔 배울가치가 있다.

 

ADO.NET은 크게 연결긴을을 하는 부분과 조작기능을 하는 부분으로 나눌수 있다. 연결기능은 다음장에서 설명하고 이번장에서는 조작기능에 관해서만 한다. 조작가능을 제공하는 클래스는 메모리 내의 DB에 대해 사용하는 것이므로 공급자에 독립적이며 모든 공급자가 공통으로 사용한다.

 

[DB설치 및 실행 > 테이블 작성]

 

데이터베이스는 여러가지 개체들의 집합이되 주로 테이블로 구성되며 테이블끼리 관계를 이룬다. 테이블은 열과 제약조건으로 스키마를 구성하며 실제 정보에 해당하는 행들의 집합을 가진다. 관계형 DB의 가장 핵심은 테이블이며 닷넷에서 테이블은 DataTable 클래스로 표현된다. DB를 구성하는 가장 기본 단위가 테이블이다.

public DataTable([strinbg tableName, string tableNamspace])

두 개의 인수를 가지는데 둘 다 생략 가능하다. 첫번째 인수는 테이블 이름이되 생략가능하거나 빈문자열을 주면 Table1, Table2 따위의 기본 이름이 부여된다. 두번째 인수는 테이블의 네임스페이스는 지정하며 같은 이름의 다른 테이블을 구분하는 역앟을 하는데 잘 사용하지 않는다. 여러 데이터 소스로부터 테이블을 가져오다 보면 우연히 이름이 중복될수도 잇어 구분을 위한 목적으로 네임스페이스를 지정할수 있도록 되어 있다.

 

스키마

테이블의 열정보와 제약 정보는 테이블의 구조인 스키마를 결정한다. 사람에 대한 테이블이라면 이름, 주소, 전화번호따위의 열이 포함될 것이고 책에 대한 테이블이라면 제목, 저자, 출판사 따위의 열이 포함 될 것이다.

DataColumn - 테이블 하나에 복수 개의 열이 포함되므로 테이블은 Column 프로퍼티로 열의 컬렉션을 관리한다. Columns 프로퍼트는 DataColumnCollection 타입이면 열의 배열이다. DataColumnCollection클래스는 열을 추가, 제거, 검색하는 Add, Remove, IndexOf 등의 메소드를 제공한다. 순거값과 이름으로부터 칼럼을 찾을수 있는 읽기 전용의 인덱서를 정의한다.

ex. 첫번째 칼럼을 얻고 싶다면 DataColumn Col = MyTable.COlumns[0];

컬렉션은 항상 제로 베이스(Zero Base)이므로 첫번째 요소의 첨자가 0이다.

DataType - DataColumn 클래스의 DataType 프로퍼티는 열이 어떤 타입의 데이터를 저장하는지, 즉 데이터의 형태가 어떠한지를 지정한다.

SQL서버타입 닷넷 타입
INT int32
BIGINT int64
NVARCHAR, NCHAR String
DATETIME DateTime
BIT Boolean
DECIMAL Decimal
VARBINARY byte[]

Constraints  - 테이블의 Constraints 프로퍼티는 ConstraintCollection 타입이며 제약조건의 배열이다. 제약 조건은 테이블에 입력될수 있는 값의 종류를 제한한다는 면에서 테이블의 구조를 결정하는 스키마의 일부로 취급된다. 제약조건에 의해 테이블에 무의미한 값이 입력되는 것이 방지되어 무결성이 유지된다.

 

테이블의 실제 데이터를 저장하는 것은 행(Record)이며 행은 DataRow 클래스로 표현한다. 이 클래스는 특이하게도 공개된 생성자가 정의되어 있지 않아 코드에서 직접 객체를 생성할수 없다. 행은 테이블의 스키마구조에 맞게 생성되야 하므로 일반적인 생성구문을 정의할수 없다.

행의 구조를 정의하기 위해서는 열과 제약조건이 먼저 정의되어야 하며 행은 테이블 내에서만 존재할수 있으므로 단족으로 생성할수 없도록 되어 있다. 행을 만들때는 DataTable 클래스의 NewRow메소드를 호출해야 하며 이 메소드는 테이블의 스키마를 참조하여 열 컬렉션을 제대로 저장할수 있는 행 객체를 생성한다. 테이블의 스키마가 먼저 확정되어야 행을 생성할수 있는 것이 당연하다.

 

테이블생성

ex.

 private DataTable MakeSaleTable()
        {
            DataTable tbSale = new DataTable("tbSale");

            DataColumn col;
            DataRow row;

            col = new DataColumn("OrderNo", typeof(Int32));
            col.AllowDBNull = false; > Primary Key 가 되는 열 생성.
            col.Unique = true;

            col.AutoIncrement = true;
            col.ReadOnly = true;
            tbSale.Columns.Add(col);

            tbSale.PrimaryKey = new DataColumn[] { col };

            col = new DataColumn("Customer", typeof(string));
            col.MaxLength = 10;
            col.AllowDBNull = false;
            tbSale.Columns.Add(col);

            col = new DataColumn("Item", typeof(string));
            col.MaxLength = 20;
            col.AllowDBNull = false;
            tbSale.Columns.Add(col);

            col = new DataColumn("ODate", typeof(DateTime));
            col.AllowDBNull = false;
            tbSale.Columns.Add(col);

            row = tbSale.NewRow();
            row["Customer"] = "김태희";
            row["Item"] = "제모기";
            row["ODate"] = new DateTime(2008, 1, 1);
            tbSale.Rows.Add(row);

            row = tbSale.NewRow();
            row["Customer"] = "차예련";
            row["Item"] = "블라우스";
            row["ODate"] = new DateTime(2008, 1, 2);
            tbSale.Rows.Add(row);

            row = tbSale.NewRow();
            row["Customer"] = "이연희";
            row["Item"] = "스커트";
            row["ODate"] = new DateTime(2008, 1, 3);
            tbSale.Rows.Add(row);

            row = tbSale.NewRow();
            row["Customer"] = "문근영";
            row["Item"] = "교복";
            row["ODate"] = new DateTime(2008, 1, 4);
            tbSale.Rows.Add(row);

 

 tbSale.AcceptChanges(); > 없어도 화면에 출력을 되지만 이 함수를 호출하게 되면 RejectChanges를 호출해도 Data 삭제 되지 않는다.


            return tbSale;
        }

 

 

테이블 편집

그리드에서의 편집

데이터를 편집하는 가장 편리한 방법이 화면의 그리드 컨트롤을 사용하는 것이다.그리드를 엑셀 워크시트라고 생각하고 원하는 셀로 이동하여 편집하면 된다. 왠만한 가능은 모두 지원된다. 이것이 가능한 이유는 DataTable객체와 그리드 콘트롤이 바인딩되어 있기때문인데 그리드뿐만 아니라 테이블과 바인딩되는 모든 콘트롤에 동일한 기능이 제공된다. 그리드는 바인딩된 테이블을 표시할뿐 아니라 사용자로부터 입력을 받아서 테이블로 다시 보내기도 하며 테이블의 제약 조건을 참조하여 엉터리 데이터가 입력되는 것을 막아주기까지 한다. 그러나 그리드는 어디까지나 최종사용자가 직접 조작하는 콘트롤이지 코드에서 그리드를 통해 데이터를 편집할수는 없다.

검색

테이블에 있는 레코드 중 지정한 조건을 만족하는 것을 찾는 것이다. 삭제나 수정을 하려면 먼저 대상 레코드를 찾아야 하므로 편집을 하기전에 먼저 해야 한다.

첫번째는 행 컬렉션의 Find 메소드를 호출하는 것이다.

public DataRow Find(Object key)

public DataRow Find(Object[] keys)

두번째는 DataTAble의 Select 메소드를 호출하는 것이다.
public DataRow[] Select(string filterExpression, string sort)

수정

ex.

 string filter = "Name = '
  " + textBoxAge2.Text + " ' ";
            DataRow[] Result = tbPeople.Select(filter);
            if (Result.Length != 0)
            {
                Result[0]["Age"] = Convert.ToInt32(textBoxNewAge.Text);
            }
            else
            {
                MessageBox.Show("그런 사람은 없어요");
            }

입력받은 이름을 찾아서 그 사람의 나이를 바꾸는 예제이다. 여기서 중요한 것은 Name =  다음에 이름을 문자열 기호 " '' 로 묶어주는 것이다.

ex.

 string filter = "Name = '" + textBoxDelete.Text + " ' ";
            DataRow[] Result = tbPeople.Select(filter);
            if (Result.Length != 0)
            {
                Result[0].Delete();
            }

Delete가 휴지통에 버리는 거라면 Remove는 완전삭제를 의미한다. 가급적 Delete를 권장한다.

그리고 수정, 삭제 후 .RejectChanges();를 호출하면 원래 상태로 돌아간다. 그러니까 DataSet에 반영하려면 .AcceptChanges();을 꼭 호출해줘야 한다.

 

 

 

 

DB 기초에 관련된 사이트 winapi/SQL

쿼리문의 종류

-DDL(Data Definition Language) - DB 오브젝트를 생성, 삭제, 변경한다. CREATE, DROP, ALTER 등의 명령이 있다. 주로 DB를 디자인하는 관리자들이 이 부류의 명령을 사용한다

-DML(Data Manipulation Language) - DB를 조작한다.  SELECT, INSERT, DELETE, UPDATE 명령 등이 있다. 응용프로그램 개발자들은 주로 이 명령을 사용하여 DB의 데이터를 조사하거나 삽입, 삭제, 변경한다.

-DCL(Data Coltrol Language) - 사용자와 권한을 관리하는 명령이다. GRANT. DENY, REVOKE 등이 있다. DBA들이 주로 쇼앙하는 일반 응용 프로그램 개발자들은 이 명령들을 사용할 일이 거의 없다. 실제로 빈도가 아주 낮다.

 

정규화

제1정규화 - 필드에 저장되는 데이터를 원자화(atomivity)하는 것이다.

제2정규화 - 기본키가 아닌 모든 필드는 기본키에 종속되도록 하는 것이다. 여기서 종속된다는 표현은 긴본키를 알면 나머지 정보도 알수 있다는 뜻이다.

제3정규화 - 기본키가 아닌 일반필드끼리는 서로 종속되지 않는다. 일반 필드끼리는 독립적이어야 한다는 규칙이며 상호종속적인 필드는 분리해야 한다.

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 9. 5. 15:49