* 질문 등록 시 다음의 내용을 꼭 기입하여 주세요.
Windows 10 | |
9.3.0 | |
[도움말]-[버전정보] 확인 | |
c# |
* CUBRID 응용 오류, SQL 오류 또는 SQL 튜닝 관련된 문의는 반드시 다음의 내용을 추가해 주세요. 비밀글이나 비밀 댓글도 가능합니다.
* 저희가 상황을 이해하고, 재현이 가능해야 알 수 있는 문제들이 많습니다. 가능한 정보/정황들을 부탁합니다.
에러 내용 및 재현 방법 | 재현 가능한 Source와 SQL |
관련 테이블(인덱스, 키정보 포함) 정보 | CUBRID 홈 디렉토리 아래 log 디렉토리 압축 |
-------------- 아래에 질문 사항을 기입해 주세요. ------------------------------------------------------------------------
adapter.Fill(dt); 부분에서
예외 발생: 'CUBRID.Data.CUBRIDClient.CUBRIDException'(CUBRID.Data.dll)
에러가 납니다. 튕겨나가지는 않고 에러가 나지만 그대로 수행이 됩니다.
adapter.fill의 에러번호를 보면 1이고 에러를 찾아보면 index's column is not object이 나옵니다.
에러가 안나게 할 수 있나요?
CUBRID.Data.dll의 파일버젼은 9.3.0.1 입니다.
소스의 일부는 아래와 같습니다.
--- 소스
DataTable dt = new DataTable();
try
{
using (CUBRIDConnection conn = new CUBRIDConnection())
{
conn.ConnectionString = Utils.connString;
conn.Open();
using (CUBRIDCommand cmd = new CUBRIDCommand(sql, conn))
{
cmd.CommandType = CommandType.Text;
CUBRIDDataAdapter adapter = new CUBRIDDataAdapter(cmd);
adapter.Fill(dt);
}
conn.Close();
}
}
catch (Exception exp)
{
throw new Exception(exp.Message);
}
주어진 코드와 오류 내용만으로는 원인을 알 수 없습니다.
DataAdapter를 이용한 예제 소스를 아래에 첨부하였으니 참고하시기 바랍니다.
using CUBRID.Data.CUBRIDClient;
using System.Diagnostics;
using System.Data;
using System;
// DataTableExample namespace 선언(namespace는 Object들의 범위)
namespace DataTableExample
{
class Program // Program class 설정
{
/* CUBRIDCommand의 ExecuteNonQuery() 메소드를 호출하는 ExecuteSQL 메소드 정의 */
private static void ExecuteSQL(string sql, CUBRIDConnection conn)
{
using (CUBRIDCommand cmd = new CUBRIDCommand(sql, conn))
{
cmd.ExecuteNonQuery();
}
}
/* 테이블명을 입력받아 Row의 수를 int형 값으로 리턴하는 GetTableRowsCount() 메소드 정의 */
private static int GetTableRowsCount(string tableName, CUBRIDConnection conn)
{
int count = -1;
string sql = "select count(*) from `" + tableName + "`";
using (CUBRIDCommand cmd = new CUBRIDCommand(sql, conn))
{
/* 단순히 숫자를 반환받기 위해 ExecuteScalar() 메소드 호출 */
count = (int)cmd.ExecuteScalar();
}
return count;
}
static void Main(string[] args)
{
string sb = "server=192.168.174.128;database=demodb;port=33000;user=public;password=;charset=utf-8";
/* 커넥션 URL을 sb 변수에 배정 */
using (CUBRIDConnection conn = new CUBRIDConnection())
{
conn.ConnectionString = sb; // ConnectionString에 URL 값을 배정
conn.Open(); // 커넥션 수립
ExecuteSQL("drop table if exists t", conn); // t 테이블이 이미 존재할 시 DROP
ExecuteSQL("create table t(dt datetime, name varchar)", conn); // t 테이블 생성
ExecuteSQL("insert into t values('3/31/2016 10:20:30.040', '테스트')", conn); // 데이터 INSERT
ExecuteSQL("drop table if exists tbl", conn); // tbl 테이블이 이미 존재할 시 DROP
// CUBRIDCommand 객체 cmd를 생성, ExecuteNonQuery() 메소드를 통해 tbl 테이블 CREATE
using (CUBRIDCommand cmd = new CUBRIDCommand("create table tbl(a int, b varchar(20))", conn))
{
cmd.ExecuteNonQuery();
}
/* 매개변수를 이용한 쿼리 수행 */
using (CUBRIDCommand cmd = new CUBRIDCommand("insert into tbl values(?, ?)", conn))
{
CUBRIDParameter p1 = new CUBRIDParameter("?p1", CUBRIDDataType.CCI_U_TYPE_INT);
/* CUBRIDParameter 객체 p1을 생성, 타입을 INT로 지정 */
p1.Value = 1; // 첫째 매개변수의 값을 1로 배정
cmd.Parameters.Add(p1); // p1을 첫번째 파라미터로 추가
CUBRIDParameter p2 = new CUBRIDParameter("?p2", CUBRIDDataType.CCI_U_TYPE_STRING);
/* CUBRIDParameter 객체 p2를 생성, 타입을 STRING으로 지정 */
p2.Value = "문자열"; // p2의 값을 '문자열' 로 배정
cmd.Parameters.Add(p2); // p2를 두번째 파라미터로 추가
cmd.ExecuteNonQuery(); // 쿼리 수행
}
/* CUBRIDDataAdapter 객체 생성을 통한 테이블 컨트롤 (sql String 변수를 통해 SQL 구문을 전달하여 데이터를 받는다) */
String sql = "select * from nation order by `code` DESC LIMIT 10";
using (CUBRIDDataAdapter da = new CUBRIDDataAdapter(sql, conn))
{
// 파라미터를 이용한 데이터 INSERT를 위해 CUBRIDCommand 객체인 daInsert 생성
CUBRIDCommand daInsert = new CUBRIDCommand("insert into nation values(?,?,?,?)", conn);
daInsert.CommandType = CommandType.Text; // 객체 생성 시 쿼리를 Text로 입력하였으므로 Text로 설정
//Parameter1: code
daInsert.Parameters.Add(new CUBRIDParameter("?p1", DbType.String));
daInsert.Parameters["?p1"].SourceVersion = DataRowVersion.Current;
daInsert.Parameters["?p1"].SourceColumn = "code"; // 첫번째 파라미터의 DataSet을 code 컬럼으로 설정
daInsert.Parameters["?p1"].SourceColumnNullMapping = false;
/* 컬럼이 NULL을 허용한다면 SourceColumnNullMapping을 true, 아니면 false 로 설정 */
//Parameter2: name
daInsert.Parameters.Add(new CUBRIDParameter("?p2", DbType.String));
daInsert.Parameters["?p2"].SourceVersion = DataRowVersion.Original;
daInsert.Parameters["?p2"].SourceColumn = "name"; // 두번째 파라미터의 DataSet을 name 컬럼으로 설정
daInsert.Parameters["?p2"].SourceColumnNullMapping = false;
//Parameter3: continent
daInsert.Parameters.Add(new CUBRIDParameter("?p3", DbType.String));
daInsert.Parameters["?p3"].SourceVersion = DataRowVersion.Current;
daInsert.Parameters["?p3"].SourceColumn = "continent"; // 세번째 파라미터의 DataSet을 continent 컬럼으로 설정
daInsert.Parameters["?p3"].SourceColumnNullMapping = false;
//Parameter4: capital
daInsert.Parameters.Add(new CUBRIDParameter("?p4", DbType.String));
daInsert.Parameters["?p4"].SourceVersion = DataRowVersion.Original;
daInsert.Parameters["?p4"].SourceColumn = "capital"; // 네번째 파라미터의 DataSet을 capital 컬럼으로 설정
daInsert.Parameters["?p4"].SourceColumnNullMapping = false;
daInsert.UpdatedRowSource = UpdateRowSource.None;
// DataAdapter에서 Update 메소드를 수행할때 DataRow에 어떻게 적용되는지 설정 (None 으로 설정하면 반환된 결과가 DataSet에 저장되지 않음)
da.InsertCommand = daInsert;
// DataAdapter 의 INSERT 명령을 daInsert에 설정한대로 작동하도록 설정
DataTable dt = new DataTable("nation");
da.Fill(dt);
/* Fill() 메소드는 DataAdapter의 SelectCommand 결과로 DataTable 객체인 dt를 채우는 역할을 한다. */
DataRow newRow = dt.NewRow(); // 행 입력을 위한 DataRow 객체 newRow 생성
newRow["code"] = "ZZZ";
newRow["name"] = "ABCDEF";
newRow["capital"] = "하하";
newRow["continent"] = "QWERTY";
dt.Rows.InsertAt(newRow, 0);
// newRow를 dt의 0번 인덱스 위치로 INSERT
da.Update(dt);
/* DataAdapter의 Update() 메소드를 통해 dt에 변경된 내역에 대해 INSERT, UPDATE, DELETE 등의 SQL문들을 호출한다. */
dt.AcceptChanges(); // 변경된 내용 모두 commit
/* Console.WriteLine() 메소드를 이용해 dt의 0번 인덱스 Row에 있는 capital 컬럼의 값을 콘솔 창에 출력 */
Console.WriteLine(dt.Rows[0]["capital"].ToString());
/* Debug 모드에서 값을 체크하기 위해 Debug.Assert 메소드 사용 */
Debug.Assert(dt.Rows[0]["capital"].ToString() == "하하");
Debug.Assert(newRow.RowState.ToString() != "New");
}
/* Debug 모드에서 값을 체크하기 위해 Debug.Assert 메소드 사용 */
Debug.Assert(GetTableRowsCount("nation", conn) == 216);
// 코드 상단에 정의한 GetTableRowsCount() 메소드를 통해 특정 컬럼의 row 수를 리턴받고 그 값이 216이 아니면 경고 창 생성)
//Revert changes
ExecuteSQL("delete from nation where `code` = 'ZZZ'", conn);
// 마지막에 추가한 code 컬럼의 값이 'ZZZ' 인 row DELETE
Debug.Assert(GetTableRowsCount("nation", conn) == 215);
// nation 컬럼의 수가 215가 아니면 경고 창 생성
conn.Close(); // 커넥션 종료
}
}
}
}