hdqqq

  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理 ::
  35 随笔 :: 0 文章 :: 104 评论 :: 0 Trackbacks
       上一篇讲到了根据一个typelist实现一个结构,这个结构带有typelist中所有类型的成员,同时,可以通过Field0,Field1等接口访问和赋值.在这个基础上,我们可以构建对应一条记录的结构data_row,

二.一条记录

#define ROW_NO_CHANGE 0
#define ROW_ADD 
1
#define ROW_UPDATE 
2
#define ROW_DELETE 
3

template
<typename _tlist>
class data_op_record_row : 
public struct_mem<_tlist>
{
public:
    enum _enum_RowState {
        _en_Row_NoChange 
= ROW_NO_CHANGE,    //未修改
        _en_Row_Add 
= ROW_ADD,            //新增记录
        _en_Row_Update 
= ROW_UPDATE,        //更新
        _en_Row_Del 
= ROW_DELETE,        //删除
    } m_en_State;
public:
    void SetState(
int newstate) {
        
if (m_en_State != newstate) {
            
if (newstate == _en_Row_NoChange || 
                newstate 
== _en_Row_Add || 
                newstate 
== _en_Row_Update || 
                newstate 
== _en_Row_Del) 
            {
                m_en_State 
= (_enum_RowState)newstate;
            }
        }
    }
public:
    data_op_record_row () : m_en_State(_en_Row_NoChange) {}
    ~data_op_record_row (){}
protected:
private:
};
上面的类增加了一个枚举,标识这条记录当前的状态,在记录集中,将根据记录的状态进行相关的操作.这个其实类似与.net中的DataRow,不过.net中的DataRow可以用wizzard生成需要的类,而这里是用模板生成的.

三.数据类型转换
      数据库中的表对应的字段有不同的数据类型,ADO操作接口中用不同的数据类型与之对应,其中Field接口的GetType就是返回字段类型的,但是ADO的GetValue返回的是_variant_t类型,为了实际业务的需要,还需要转换成不同的类型,因此,需要对_variant_t类型进行转换.为此需要提供模板转换函数

template <typename _type>
void DbData_Change(_type
& ret, _variant_t& field)
{
   AfxMessageBox(
"未定义的数据转换");
}


template 
<>
void DbData_Change
<int>(int & ret, _variant_t& field)
{
    ret 
= field.lVal;
}

template 
<>
void DbData_Change
<std::string>(std::string& ret, _variant_t& field)
{
    _bstr_t temp;

    
if (field.vt != VT_NULL) {
        temp 
= field.bstrVal;
        ret 
= temp.operator const char*();
    }
}

template 
<>
void DbData_Change
<bool>(bool& ret, _variant_t& field)
{
    ret 
= (field.boolVal == (short)0xFFFF ? TRUE : FALSE);
}

template 
<>
void DbData_Change
<double>(double& ret, _variant_t& field)
{
    
if (field.vt != VT_NULL) {
        
//ret = field.cyVal;
        ret 
= field.dblVal;
    }
else {
        ret 
= 0;
    }
}

上面的模板函数的功能是从_variant_t转换到某中数据类型,对于其它类型还可以进行扩充,对于没有进行特化的函数,编译器会使用缺省模板,在运行时候就会出现提示.有了上面的函数,现在我们需要一个数据类型的封装类,使得被封装的类型可以自动进行从_variant_t类型的需要类型的转换,所以有了下面的封装类.
//数据库数据类型封装
template 
<typename _type>
class _db_data_wrapper
{
public:
    _type
& Value() {
        return m_Data;
    }

    
const _type& operator =(const _type& value) {
        m_Data 
= value;
        return value;
    }

    _db_data_wrapper
& operator = (const _db_data_wrapper& other) {
        
if (this != &other) {
            m_Data 
= other.m_Data;
        }
        return 
*this;
    }

public:
    virtual void GetDbValue(_variant_t
& field_value) {
        DbData_Change(m_Data, field_value);
    }

public:
    _db_data_wrapper(){}
    _db_data_wrapper(
const _type& value) : m_Data(value) {}
    ~_db_data_wrapper(){}
private:
    _type m_Data;
};

typedef _db_data_wrapper
< int > DB_INT;
typedef _db_data_wrapper
< std::string > DB_STRING;
typedef _db_data_wrapper
< bool > DB_BOOL;
typedef _db_data_wrapper
< double > DB_DOUBLE;



上面的代码预定义了几种常用的数据类型,这个数据的封装类支持 = 操作符,因此可以直接用被封装的数据对其赋值.象下面
int i = 4;
DB_INT di;
di 
= i;
= di.Value();


同时通过成员函数GetDbValue(_variant_t& field_value), 支持从_variant_t转换为自身封装的类型.

现在,可以用上面的数据类型构建记录结构了

typedef data_op_record_row< TYPELIST_2(DB_INT,DB_STRING) > my_DataRow;

在上面的my_DataRow类型中,有两个成员Field0, Field1,类型分别为 DB_INT,DB_STRING, 支持_variant_t类型转换.

当然,用wrapper对数据进行封装在实际的使用中毕竟有些麻烦, 如数据必须通过 Value() 函数来取得,如果直接使用象 int, std::string 等类型作为 记录结构的成员,也可以实现_variant自动转换,但是需要在上一层的记录集类中加入相关的转换操作,实现起来比较麻烦,所以我这里选择了对数据进行封装.


 

posted on 2007-01-22 17:33 hdqqq 阅读(1225) 评论(1)  编辑 收藏 引用 所属分类: c/c++

评论

# re: 创建一个基于模板的数据库记录集操作类(二) 2007-01-24 09:44 天下无双
看到模板,我就有些不明白了。  回复  更多评论
  


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理