400 likes | 761 Views
성적처리. MFC(DataBase 연동 ). 1. 성적관리 프로그램. 기본 MFC DataBase 관련 클래스. DB Application 과 DBMS . DB Application DB 에 접근하여 데이터를 추가 , 수정 , 삭제 등을 위한 인터페이스를 제공하는 프로그램 입니다 . DBMS(Database Management System) 실제 DB 를 다루는 기능을 하는 것으로서 DB Application 은 사용자와 DBMS 사이의 인터페이스를 제공할뿐이다.
E N D
성적처리 MFC(DataBase 연동)
1.성적관리 프로그램 기본 MFC DataBase 관련 클래스
DB Application 과 DBMS • DB Application DB에 접근하여 데이터를 추가, 수정, 삭제 등을 위한 인터페이스를 제공하는 프로그램 입니다. • DBMS(Database Management System) 실제 DB를 다루는 기능을 하는 것으로서 DB Application은 사용자와 DBMS사이의 인터페이스를 제공할뿐이다.
MFC DB 관련 클래스 • CDatabase • Crecordset • CRecordView • CDBException
CDatabase Class virtualBOOLOpen(LPCTSTRlpszDSN,BOOLbExclusive = FALSE,BOOLbReadOnly = FALSE,LPCTSTRlpszConnect = “ODBC;”,BOOLbUseCursorLib=TRUE); -DB가 열리면 TRUE를 열리지 않으면 FALSE를 Return 해준다. • Ex> CDatabase database; • database .Open( “Grade” , FALSE , FALSE,”_T(“ODBC;DNS=Grade”),TRUE); • database .Open( “Grade” , FALSE , FALSE,”_T(“ODBC; DNS=Grade”)); • database .Open( “Grade”); dsn 이름을 적어준다. virtualvoidClose(); • Ex> • database .Close(); - Open한 DB는 항시 Close를 해주어야 한다.-
Cdatabase Class • virtual BOOL OpenEx( LPCTSTRlpszConnectString, DWORDdwOptions= 0); • 확장형 DB오픈 함수 • Ex> • database.OpenEx( _T( "DSN=MYDATASOURCE;UID=JOES" ), CDatabase::openReadOnly CDatabase::noOdbcDialog ); • database.OpenEx(_T(“DRIVER={Microsoft Access Driver *.mdb)};DBQ=c:\a.mdb”)
Cdatabase Class • 그밖의 자주 사용하는 함수들 • CStringGetDatabaseName()const; - DB의 이름을 Cstring형으로 return 해준다. • ex> CString DB_NAME = database . GetDatabaseName(); • BOOL IsOpen( ) const; - DB가 열려져 있는지 검사한다. (open상태이면 TRUE 아니면 0) • ex> if( database . IsOpen() == FALSE)) //열려져 있지 않으면.. • voidExecuteSQL(LPCSTRlpszSQL);- 직접 Sql 문을 실행시킨다. - database .ExecuteSQL(“INSERT INTO MY_TABLE (Name) VALUES (‘100’)”)
CRecordSet Class • 레코드들의 집합(테이블과 같은것) • DB에 관련된 집접적인 일들을 하기 때문에 Doc에 객체를 생성 View에서 이 객체를 이용하여 DB에 관련된 일을 한다. • CRecordView와 DB간의 중간 역할.
CRecordSet Class • 레코드셋 Open 하기 • virtualBOOLOpen(UINTnOpenType=AFX_DB_USE_DEFAULT_TYPE,LPCTSTRlpszSQL=NULL,DWORDdwOptions=none); • Ex> CRecordSet my_Set; • my_Set.Open(AFX_DB_USE_DEFAULT_TYPE, NULL, none); • my_Set.Open(CRecordset::dynaset); • my_Set.Open(); • virtualvoidClose(); • Ex> my_Set.Close();
CRecordSet Class • DB 의 컬럼들(변수) • CRecordSet m_Set;(내가 사용할 레코드셋 선언)
CRecordSet Class • virtualvoidDoFieldExchange(CFieldExchange*pFX); • void CRecordSet::DoFieldExchange(CFieldExchange* pFX) { //{{AFX_FIELD_MAP(CGradeSet) pFX->SetFieldType(CFieldExchange::outputColumn); RFX_Text(pFX, _T("[strName]"), m_strName); RFX_Text(pFX, _T("[strNumber]"), m_strNumber); RFX_Long(pFX, _T("[nKorean]"), m_nKorean); RFX_Long(pFX, _T("[nEnglish]"), m_nEnglish); DB변수명 RecordSet 변수명 //}}AFX_FIELD_MAP } • DoFieldExchange에서 DB들의 데이터를 우리가 사용할수 있게 해주는 일을 해준다.
CRecordSet Class • 자주 사용하는 함수들 • virtualBOOLUpdate();하나의 레코드들이 똑바로 등록되었을때 이를 최종적으로 업데이트 해줍니다. 추가,삭제 후 항시 불려지는 함수입니다. 이 함수가 불려지지 않으면 레코드에 데이터들이 저장되지 않습니다.
CRecordSet Class • 추가 • virtualvoidAddNew(); • ex> m_Set.AddNew(); 새로 컬럼들을 생성합니다. m_Set.m_strName=“저장할이름”; m_strNumber=“번호네”; m_nKorean=10; m_nEnglish=20; m_Set.Update();추가,수정 후 항시 해주어야 합니다. • Tip : DB의 컬럼중 필수 사항인것과 중복을 허용하지 않는 컬럼이 있는 경우 잘못입력시 값이 저장되지 않습니다.
CRecordSet Class • 수정 • virtualvoidEdit(); • ex> m_Set.Edit(); 현재 컬럼들을 수정합니다. m_Set.m_strName=“변경할이름”; m_strNumber=“변경할 번호네”; m_nKorean=40; m_nEnglish=50; m_Set.Update();추가,수정 후 항시 해주어야 합니다. • Tip : DB의 컬럼중 필수 사항인것과 중복을 허용하지 않는 컬럼이 있는 경우 잘못입력시 값이 저장되지 않습니다.
CRecordSet Class • 삭제 • virtualvoidDelete(); • ex> m_Set.Delete(); • 삭제하고자 하는 레코드를 선택후 Delete()함수만을 불러 줌으로서 간단히 지울수 있습니다. * Tip: 레코드셋은 디비 전체가 저장되는것이 아니라 각 디비의 한줄씩 저장된다고 생각하시면 됩니다. 지우고자 하는 디비가 몇번째 인지 알면은 간단히 지울수 있습니다.
CrecordSet Class • virtualBOOLRequery(); • 쿼리를 다시 실행하는것입니다. 다시 예기해서 SQL에 쿼리문 실행하는것이라 생각하시면 되겠네요.
CRecordSet Class • 정렬 • CRecordset::m_strSort • m_strSort 라는 스트링형 변수에 SQL문중비교하는 부분만 적어주시면됩니다. • ex> m_Set.m_strSort=“nKorean DESC“; <- 내림차순으로 m_Set.Requery(); 항시 찾기 및 정렬후 해주어야 합니다. • 리쿼리 문을 실행하고 나면 m_Set은 그 정렬된후의 DB의 값을 가지게 됩니다. • Tip : m_strSort =_T(“”); m_Set.Requery(); 정렬 전 상태로 DB가 돌아 갑니다.
CRecordSet Class • 찾기 • CRecordset::m_strFilter • 사용방식은 정렬과 동일합니다. • ex> m_Set.m_strFilter=“strName = ‘하하하’ “; <- 하하하 찾기 m_Set.Requery(); 항시 찾기 및 정렬후 해주어야 합니다 • m_strFilter 에 쿼리문 SELECT * FROM TABLE WHERE 이후 부터적어주시고 Requery()를 호출해주시면 됩니다. • 정렬과 같게 찾은 DB의 값이 레코드셋에 저장됩니다. 만약 찾은값이 3개이면 3개의 DB의 값들이 저장됩니다. • Tip:Tip : m_strFilter =_T(“”); m_Set.Requery(); 전체 DB로 돌아 갑니다.
CRecordSet Class • 기본 적으로 생기는 함수들 • virtualCStringGetDefaultConnect(); 디폴트로 연결되어지는 디비를 설정하는곳이다. 오버라이딩된 이 함수를 지워주면 디비연결이 되지 않아서 에러가 난다. 이부분을 지워 주었을때는Doc에서 DB연결부분을 View에서 사용할 레코드셋 설정을 해주어야 한다. • Ex>CString CRecordSet::GetDefaultConnect() { return _T("ODBC;DSN=Grade"); }
CRecordSet Class • 기본 적으로 생기는 함수들 • virtualCStringGetDefaultSQL(); 디폴트로 얻어지는 SQL문이다. 기본적으로 처음 연결된 테이블 이름이 나와 있다. • Ex> CString CRecordSet::GetDefaultSQL() { return _T("[Student]"); } • 여러 개의 테이블과 연결되어 있으면 그 테이블 이름이 다 리턴된다. • Return _T(“SELECT [student].[strName], [Subject].[strSubject] FROM student INNER JOIN Subject On [student].[nSub_Num]= [Subject].[nNum]”); 이런식으로 필요한 데이터들만 추출할수도 있다.
CRecordSet Class • 그외 자주 쓰이는 함수들 • BOOLIsOpen()const; 현재 레코드셋이 열려 있는지 확인. • ex>if(!m_Set.IsOpen())열려 있지 않으면 m_Set.Open(); 레코드셋열어라.. * Tip : 레코드셋을 열때는 항시 위와 같은 형식으로 열어야 된다. 이유는 추가 및 수정등을 할때 Update()를 호출하지 못하고 끝나버리면 중간에 다시 처음부분으로 가버리기 때문에 다시 Open함수를 호출하게 되면 에러가 난다 • BOOLIsBOF()const; 현재 레코드셋이 처음인지 확인. Ex> if(m_Set.IsBOF()){AfxMessageBox(“처음”)}; • BOOLIsEOF()const; 현재 레코드셋이 끝부분인지 확인. Ex> if(m_Set.IsEOF()){AfxMessageBox(“끝”)};
CRecordSet Class • 그외 자주 쓰이는 함수들 • voidMoveFirst(); 레코드셋을 처음으로 이동시킨다. Ex>m_Set.MoveFirst(); • voidMoveLast(); 레코드셋을 마지막으로 이동시킨다. Ex>m_Set.Move Last(); • voidMoveNext(); 레코드셋을 다음으로 이동시킨다. Ex>m_Set.MoveNext(); • voidMovePrev(); 레코드셋을 전으로 이동시킨다. Ex>m_Set.Move MovePrev();
CRecordView Class • 레코드셋의 데이터를 레코드 단위로 화면에 보여주는 기능을 가지고 있는 Cview의파생 클래스 입니다. 레코드뷰를 사용하면 레코드셋에 저장되어 있는 데이터를 화면에 표시하는 루틴을 직접 작성하지 않아도 자동으로 스크롤해가면서 화면에 보여줍니다. • 레코드의 데이터와 컨트롤을 연결시키기위해 내부적으로 CFieldExchange클래스를 사용합니다. • 한번에 하나의 레코드만을 화면에 보여줄수 있기 때문에 , 자신이 이형식을 원하지 않으면 집적 코드를 작성 하여야 합니다.
CRecordView Class • 내부적으로 CFieldExchange클래스를 사용하여 레코드셋의 변수를 컨트롤과 직접 직접연결 함으로서 매우 간단히 DB의 내용들을 보여줄수 있다. • 아래 화면에서 컨트롤의 변수를 정할때 m_pSet->xxx 식의 레코드셋의 변수를 바로 연결해줄수 있다.
CDBException Class • DB처리 작업중 발생하는 에러에 대한 처리를 담당합니다. • ex> try { m_Set.Open(); } catch(CDBException* e) { AfxMessageBox(e->m_strError);무슨에러인지 출력 e->Delete(); 에러를 지운다. return NULL; 만약 리턴값이 있는 함수이면.. }
프로젝트 생성하기 • 레코드셋과 연결할 테이블을 선택합니다. 3개다 포함하고 싶으면 3개다 선택하면 됩니다. * Tip : 레코드셋을 선택할때 전체다 선택하지말고각각의 레코드셋을 따로 두어서 해당 테이블에 관한일은 그 레코드셋이 할수 있도록 한다.
레코드셋 선언하기 • Document에서 레코드셋의 해더파일을 include해주고 그 객체를 선언하여 준다. 이 선언한 객체를 이용하여 DB에 접근한다.
새로운 뷰와 레코드셋연결하기 • CRecordView로 상속받으며 IDD_NEWVIEW(미리 만들어 놓은 View 다이얼로그)를 정해주어야 한다.
DB 수동 연결 하기 1 .CDatabase m_DB 2 . m_DB.Open(_T("Grade"), FALSE, FALSE, _T("ODBC;DNS=Grade")); 3 . if(!m_DB.IsOpen()) 4 . { 5 . CString FilePath; CString ConnectString; 6 . CFileDialog dlgFile(TRUE,_T(".mdb"),NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,_T("데이터베이스 파일(*.mdb)|*.mdb|모든파일(*.*)|*.*||")); 7 . FilePath=dlgFile.GetFileTitle(); 8 . ConnectString = "DRIVER={Microsoft Access Driver (*.mdb)};DBQ="+FilePath; 9 . m_DB.OpenEx(ConnectString); 10. } 11. m_gradeSet.m_pDatabase=&m_DB; 12. m_SubjectSet.m_pDatabase=&m_DB; 13 .m_TermSet.m_pDatabase=&m_DB; 14. m_gradeSet.Open(CRecordset::dynaset); 15. m_SubjectSet.Open(CRecordset::dynaset); 16. m_TermSet.Open(CRecordset::dynaset);
DB 수동 연결 하기 • 소스분석 및 해석 • Doc에서 DB연결 부분을 작성한다. 1 . CDatabase m_DB 사용할 DB 선언 2 . m_DB.Open(_T("Grade"), FALSE, FALSE, _T("ODBC;DNS=Grade")); 먼저 Grade (DB)가 ODBC에 등록 되어 있는지 확인하여 연다. 3 . if(!m_DB.IsOpen()) 열려 있지 않으면 4 . { 5. CString FilePath; CString ConnectString; 사용할 변수 선언 6 . CFileDialog dlgFile(TRUE,_T(".mdb"),NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,_T("데이터베이스 파일(*.mdb)|*.mdb|모든파일(*.*)|*.*||")); 파일을 선택하기 위해 다이얼로그를 연다. 7. FilePath=dlgFile.GetFileTitle(); 파일의 위치 얻기 8 . ConnectString = "DRIVER={Microsoft Access Driver (*.mdb)};DBQ="+FilePath; OpenEx함수에 들어갈 옵션들을 저장 9 . m_DB.OpenEx(ConnectString); OpenEx함수 호출 10. } • 여기까지 하면은 DB가 연결된다. • * Tip : DBQ is the database qualifier. This is the fully qualified, default, working namespace.
DB 수동 연결 하기 • 소스분석 및 해석 • m_gradeSet, m_SubjetSet,m_TermSet은 각각의 레코드셋으로 Doc에서 선언되어 있으며 View에서 이 레코드셋들을 이용해서 처리한다. 11 . m_gradeSet.m_pDatabase=&m_DB; 12 . m_SubjectSet.m_pDatabase=&m_DB; 13 . m_TermSet.m_pDatabase=&m_DB; 각 레코드셋들의 DB를 현재 Open한 DB로 저장시킨다. 14 . m_gradeSet.Open(CRecordset::dynaset); 15 . m_SubjectSet.Open(CRecordset::dynaset); 15 . m_TermSet.Open(CRecordset::dynaset); 각 레코드셋들을 dynaset형식으로 Open하여 준다. • Tip : DB를 레코드셋과 연결하거나 오픈할때 설정할수 있는데 보통 Snapshot 와 Dynaset로 설정할수 있으며 그외는 MSDN 참조….ㅡ_ㅡ; SnapShot 는 읽기 전용이며 Dynaset는 읽기와 쓰기를 할수 있다.
DB 수동 연결 하기 • 그 외 …… • CDaoDatabase(DAO)와 Cdatabase(ODBC)의 클래스 사용법은 거의 같다고 생각하면 된다. • Doc에서 만든 이 함수를 DB를 사용하기 전에 불러야 한다. 만약 View가 하나이면 OnInitialUpdate() 에서 제일 먼저 DB를 불러 들이는 함수를 쓰는 것이 좋다 • View가 여러 개인 경우는 (다중뷰) 코딩방법에 따라 달라 지겠지만 위의 소스를 사용하면은 제일 처음 불리는 뷰의 OnInitialUpdate() 에서 DB를 불러 들이는 함수를 써야 한다. • 우리 교제에는 (흔히 눈깔책 또는 검은책) 다중뷰할때 각 뷰마다 각각 DB연결부분을 잃어 들인다. 그리고 교제는 CDaoDatabase(DAO) 클래스를 사용하였기 때문에 책 따라서 하면은 아마 되지 않을까..라는 생각이 든다. 해보지 않아서.. ㅡ_ㅡ;
ODBC 가상 등록하기 • ODBC를 사용하기 위해 등록을 하는데 이를 프로그램상으로 한다. • BOOL SQLConfigDataSource(HWND hwndParent, WORD fRequest, LPCSTR lpszDriver, LPCSTR lpszAttributes); 1 . CHAR szDriver[] = "Microsoft Access Driver (*.mdb)"; 데이터원본(ODBC)보면 driver라고 나와있는거. 2 . CString path = "c:\\temp"; 파일경로를 저장하기 위한 변수 3 . CString Attribute; 속성 저장하기 위한 변수 4 . Attribute = "DSN=DB_P;" 속성값들..자세한건 MSDN… "DESCRIPTION= DB_P;" DSN 이름 ODBC에 이이름으로 설정됨 "FileType = Access;" 파일 타입. "DataDirectory=C:\\temp\\DB;" 데이터 경로 "DBQ="c:\\DB\\DB_P.mdb;" "MaxScanRows=20"; 여기 까지가 속성을 결정하는것이다. 5 . if( !SQLConfigDataSource(NULL, ODBC_ADD_DSN, szDriver, Attribute)) AfxMessageBox("데이터 원본 소스(DSN) 설정에 문제가 있습니다.");] • ODBC_ADD_DSN 이 추가 한다는 옵션이다. 삭제는 ODBC_REMOVE_DSN 이다
ODBC 가상 등록하기 • EX> Excel 로 설정할경우 SQLConfigDataSource(NULL,ODBC_ADD_DSN, "Excel Files (*.xls)","DSN=New Excel Data Source\0" "Description=New Excel Data Source\0" "FileType=Excel\0" "DataDirectory=C:\\EXCELDIR\0" "MaxScanRows=20\0"); • 참고로 이함수를 사용할때 필요한 헤더와 라이브러리.. 헤더 : #include <odbcinst.h> 라이브러리 : odbccp32.lib • 위의 코드는 API 함수를 이용하여 한것이며 클래스를 따로 만들어서 사용하는것이 좋은 방법일것이다. • 더 자세한 것은 MDSN을 참고 한다.
추가 설명 • ODBC(Opne Database Connectivity) ODBC는 DB 애플리케이션과 DBMS를 연결시켜주는 표준적인 인터페이스를 제공한다. ODBC를 이용하면 DBMS의 종류에 상관없이 ODBC드라이버를 제공하는 어떤 DBMS와도 연동할 수 있다. • DAO(Data Access Object) DBMS와 인터페이스를 제공한다는 점에서 ODBC와 같다. 내부적으로는 완전히 다른 것이지만, 사용법은 같다. • ODBC는 네트워크를 지원하며 다중 사용자가 데이터베이스에 접속할 수 있도록 해 주지만 , DAO는 네트워크를 이용하여 데이터베이스에 접속할 수 없다. 그러나 DAO가 ODBC보다 빠르게 동작하며 ODBC에서 지원되지 않는 기능을 몇 가지 더 가지고 있다.
ODBC 및 DB 참조 사이트 • http://www.microsoft.com/data/odbc참고로 다 영어다..ㅡ_ㅡ;..
End Of Story • ㅡ_ㅡ;..프로그램 2틀 소요… • Power Point ㅡ_ㅡ;..오래 걸림..깨짝 깨짝해서리 오래 걸렷음. • DBQ 란 DB의 모든 권한을 주는것을 말한다. 즉 앞에서 DBQ= xx 하며은 xx에게 DB의 모든 권한을 준다는 말이다.ㅡ_ㅡ;…해석하느라 고생하셨습니다. • MSDN에도 나오지 않는 형식이 있다는것을 알아 두시길…ㅡ_ㅡ;..영어라 뭔 말인지는 모르것지만…ㅠ_ㅠ…주절 주절…