zoukankan      html  css  js  c++  java
  • Wince SQLServerCe 本地数据库读写实现

    前言:手持设备使用中,网络环境无非3种,WIFI,GPRS,3G,第一种在仓库操作中较为常见,因为使用无线网覆盖整个仓库区域还是一般仓库的标配。可是对于配送系统人员来讲,大部分使用的还是GPRS跟3G网络,这样的话对于系统的网络流量控制就显得由为重要,这样的前提下,本地数据库就很符合此场景。

        SqlServerCe是微软在Compact Framework对数据库操作的实现,其中就有对本地.sdf文件的读写。我们可以将很多程序元数据放在此数据库中,每次登陆时检查数据文件的版本用来更新一下数据库文件或者当设备在WIFI环境下手动更新一下数据库文件版本,之后再进行更新。下面就简单贴一下该方法的实现:

    1.数据库文件。

      本文是采用预定义数据库文件的方式,这样你可以再编译的时候就把数据库文件生成从而一起发布至客户端,当然你也可以在代码中创建你的database.sdf文件

      创建Data目录,新建一个sdf文件命名为testDb.Sdf

    2.SelHelper类

      这个类是我在网上搜到的一个类,相当好用,但是实际操作起来有些BUG,我就加以修改调试一下

      public class SqlHelper
    {
    #region 数据返回标签
    public const int OP_SUCESS = 0; //执行成功
    public const int OP_SYSTEMERR = -1; //用-1表示 系统异常
    public const int OP_DATABASECONNECTIONERR = -10;
    public const int OP_DATABASEEXISTS = 1; //用1表示执行不成功,已经存在该数据库了
    public const int OP_DATABASENOEXISTS = 2; //返回值2 表示不存在数据库文件
    public const int OP_ROLLBACK = 3;
    #endregion

    #region 类成员变量
    private string DataBaseName = ""; //数据库名称
    private string DataBaseConn = "";
    private string DataBaseFile = "";
    private System.Data.SqlServerCe.SqlCeEngine MySqlCeEngine = null; //数据库引擎对象,用于创建数据库
    private System.Data.SqlServerCe.SqlCeConnection MySqlCeConnection = null; //数据库连接对象
    private System.Data.SqlServerCe.SqlCeCommand MySqlCeCommand = null; //执行SQL指令的对象
    private System.Data.SqlServerCe.SqlCeTransaction MySqlCeTransaction = null; //数据库事务对象
    private System.Data.SqlServerCe.SqlCeDataReader MySqlCeDataReader = null; //数据库读写器
    private System.Data.SqlServerCe.SqlCeDataAdapter MySqlCeDataAdapter = null; //适配器
    private System.Data.DataSet MySqlCeDataSet = null; //DataSet
    private System.Data.DataView MySqlCeDataView = null; //DataView
    #endregion

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="aDataBaseName">数据库文件名</param>
    /// <param name="aDataBaseConn">数据库连接字符串</param>
    public SqlHelper(string aDataBaseName, string aDataBaseConn)
    {
    //如何只传文件名,则用默认的连接字符串,否则用用户传入的连接字符串,因为本工程SDF放在\DATA\下面所以在当前路径之后增加了这个文件夹的路径
    this.DataBaseName = aDataBaseName;
    if (string.IsNullOrEmpty(aDataBaseConn))
    {
    this.DataBaseConn = "Data Source ="
    + Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)
    + "\\data",this.DataBaseName)
    ;
    }
    else
    {
    this.DataBaseConn = aDataBaseConn;
    }
    DataBaseFile = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase)+ "\\data",
    this.DataBaseName);


    }

    #region 释放资源
    public void SqlCe_Dispose(bool disposing)
    {
    if (disposing)
    {
    if (this.MySqlCeEngine != null)
    {
    this.MySqlCeEngine.Dispose();
    this.MySqlCeEngine = null;
    }

    if (this.MySqlCeDataReader != null)
    {
    this.MySqlCeDataReader.Dispose();
    this.MySqlCeDataReader = null;
    }

    if (this.MySqlCeTransaction != null)
    {
    this.MySqlCeTransaction.Dispose();
    this.MySqlCeDataReader = null;
    }

    if (this.MySqlCeCommand != null)
    {
    this.MySqlCeCommand.Connection.Close();
    this.MySqlCeCommand.Dispose();
    this.MySqlCeCommand = null;
    }

    if (this.MySqlCeConnection != null)
    {
    this.MySqlCeConnection.Close();
    this.MySqlCeConnection.Dispose();
    this.MySqlCeConnection = null;
    }

    if (this.MySqlCeDataAdapter != null)
    {
    this.MySqlCeDataAdapter.Dispose();
    this.MySqlCeDataAdapter = null;
    }

    if (this.MySqlCeDataSet != null)
    {
    this.MySqlCeDataSet.Clear();
    this.MySqlCeDataSet = null;
    }

    if (this.MySqlCeDataView != null)
    {
    this.MySqlCeDataView.Dispose();
    this.MySqlCeDataView = null;
    }
    }//是否释放资源
    }
    #endregion

    #region 建立数据库
    virtual public int SqlCe_CreateDataBase()
    {
    //使用try...catch机制防止系统出错
    try
    {
    if (File.Exists(DataBaseFile))
    {
    return OP_DATABASEEXISTS; //用1表示执行不成功,已经存在该数据库了
    }
    else
    {
    this.MySqlCeEngine = new System.Data.SqlServerCe.SqlCeEngine(this.DataBaseConn);
    this.MySqlCeEngine.CreateDatabase();
    this.MySqlCeEngine.Dispose();
    this.MySqlCeEngine = null;
    return OP_SUCESS; //用0表示函数执行成功,建立了目标数据库
    }

    }
    catch (Exception exception)
    {
    var i = exception.Message;
    return OP_SYSTEMERR; // 用返回值-1 表示函数执行不成功,系统异常
    }
    }
    #endregion

    #region 删除数据库
    virtual public int SqlCe_DeleteDataBase()
    {
    try
    {
    if (File.Exists(this.DataBaseFile))
    {
    File.Delete(this.DataBaseFile);
    return OP_SUCESS;
    }
    else
    {
    return OP_DATABASENOEXISTS; //返回值2 表示不存在数据库文件
    }
    }
    catch (Exception)
    {

    return OP_SYSTEMERR; //返回值1函数执行不成功 系统异常 ;
    }
    }
    #endregion


    #region 连接数据库
    private SqlCeConnection SqlCe_Connect()
    {
    try
    {
    SqlCeConnection conn = null;
    if (File.Exists(DataBaseFile))
    {
    if (this.MySqlCeConnection != null)
    {
    this.SqlCe_Dispose(true);
    }
    conn = new SqlCeConnection(this.DataBaseConn);
    return conn;
    }
    else
    {
    return null;
    }
    }
    catch (Exception)
    {

    return null;
    }
    }
    #endregion

    #region 执行一组无返回的sql语句
    virtual public int SqlCe_ExecuteNonReturnSql(string[] SqlCe_Sql)
    {
    try
    {
    this.MySqlCeConnection = this.SqlCe_Connect(); //建立数据库连接
    if (this.MySqlCeConnection != null)
    {
    try
    {
    this.MySqlCeConnection.Open();
    this.MySqlCeTransaction = this.MySqlCeConnection.BeginTransaction();//建立数据库事务
    this.MySqlCeCommand = this.MySqlCeConnection.CreateCommand();//建立SqlCECommand对象
    this.MySqlCeCommand.Transaction = this.MySqlCeTransaction;
    for (int i = 0; i < SqlCe_Sql.GetLength(0); i++)
    {
    this.MySqlCeCommand.CommandText = SqlCe_Sql[i]; //传入要执行的SQL语句
    this.MySqlCeCommand.ExecuteNonQuery(); //执行语句
    }
    this.MySqlCeTransaction.Commit();//提交事务
    return OP_SUCESS; //返回0 表示事务提交成功
    }
    catch (Exception)
    {
    this.MySqlCeTransaction.Rollback();
    return OP_ROLLBACK; // 返回3 表示 事务回滚成功

    }
    }
    else
    {
    return OP_DATABASECONNECTIONERR;//返回10 表示数据库连接丢失
    }
    }
    catch (Exception)
    {

    return OP_SYSTEMERR; //返回1 系统异常
    }
    finally
    {
    this.SqlCe_Dispose(true); //事务已经提交,释放资源
    }
    }
    #endregion

    #region 返回一个SqlCeDataReader
    virtual public SqlCeDataReader SqlCe_ExecuteReturnDataReaderSql(string SqlCe_SelectSql)
    {
    try
    {
    this.MySqlCeConnection = this.SqlCe_Connect();
    if (this.MySqlCeConnection != null)
    {
    this.MySqlCeConnection.Open();
    this.MySqlCeCommand = this.MySqlCeConnection.CreateCommand();
    this.MySqlCeCommand.CommandText = SqlCe_SelectSql;
    return this.MySqlCeCommand.ExecuteReader();
    }
    else
    {
    return null; //返回null 可能连接丢失
    }
    }
    catch (Exception)
    {

    return null; //如果返回null, 可能sql语句出错 ;
    }
    finally
    {
    this.SqlCe_Dispose(false); //注意这里不能释放连接及资源,必须等所有的操作完成之后再由用户程序调用SqlCe_Dispose(true)来释放资源
    }
    }
    #endregion

    #region 返回一个SqlCeDataAdapter
    virtual public SqlCeDataAdapter SqlCe_ExecuteReturnDataAdapterSql(string SqlCe_SelectSql)
    {
    //注意:SqlCeDataAdapter要求在线操作,既数据库连接不能断开,
    //如果返回NULL, 可能连接失败,可能SQL语句出错
    try
    {
    SqlCeDataAdapter sda = null;
    this.MySqlCeConnection = this.SqlCe_Connect();
    if (this.MySqlCeConnection != null)
    {
    MySqlCeConnection.Open();
    sda = new SqlCeDataAdapter(SqlCe_SelectSql, this.MySqlCeConnection);
    return sda;
    }
    else
    {
    return null;
    }
    }
    catch (Exception)
    {

    return null;
    }
    finally
    {
    this.SqlCe_Dispose(false); //注意此处不能释放资源
    }
    }
    #endregion

    #region 返回一个DataSet
    virtual public DataSet SqlCe_ExecuteReturnDataSetSql(string selectSql)
    {
    try
    {
    DataSet ds = new DataSet();
    this.MySqlCeConnection = this.SqlCe_Connect();
    if (this.MySqlCeConnection != null)
    {
    this.MySqlCeConnection.Open();
    this.MySqlCeDataAdapter = new SqlCeDataAdapter(selectSql, this.MySqlCeConnection);
    this.MySqlCeDataAdapter.Fill(ds, "MySqlCeDataSet");
    return ds;
    }
    else
    {
    return null;
    }
    }
    catch (Exception exception)
    {
    var i = exception;
    return null;
    }
    finally
    {
    this.SqlCe_Dispose(false); //注意不要释放资源
    }
    }
    #endregion

    #region 返回一个DataView
    virtual public DataView SqlCe_ExecuteReutrnDataViewSql(string selectSql)
    {
    try
    {
    this.MySqlCeDataSet = new DataSet();
    DataView dw = null;
    this.MySqlCeConnection = this.SqlCe_Connect();
    if (this.MySqlCeConnection != null)
    {
    this.MySqlCeConnection.Open();
    this.MySqlCeDataAdapter = new SqlCeDataAdapter(selectSql, this.MySqlCeConnection);
    this.MySqlCeDataAdapter.Fill(this.MySqlCeDataSet, "MySqlCeDataSet");
    dw = new DataView(this.MySqlCeDataSet.Tables["MySqlCeDataSet"]);
    return dw;
    }
    else
    {
    return null;
    }
    }
    catch (Exception)
    {

    return null;
    }
    finally
    {
    this.SqlCe_Dispose(false); //注意
    }
    }
    #endregion

    }

    这个类基本上完成了所有对SQL数据库的增删改查操作,一般情况下,本人不是很建议在程序中对表结构乃至数据库结构做修改,尽量使发布的脚本只修改数据而不去操作表结构。

    由于我们系统是使用Nhinerbate对数据都是面向对象操作,所以不是很喜欢操作DataSet,DataReader等数据,于是我又加了一个List<T>跟DataSet相互切换的类:

    public static  class IListDataSet
    {
    /// <summary>
    /// 集合装换DataSet
    /// </summary>
    /// <param name="list">集合</param>
    /// <returns></returns>
    /// 2008-08-01 22:08 HPDV2806
    public static DataSet ToDataSet(IList p_List)
    {
    DataSet result = new DataSet();
    DataTable _DataTable = new DataTable();
    if (p_List.Count > 0)
    {
    PropertyInfo[] propertys = p_List[0].GetType().GetProperties();
    foreach (PropertyInfo pi in propertys)
    {
    _DataTable.Columns.Add(pi.Name, pi.PropertyType);
    }
    for (int i = 0; i < p_List.Count; i++)
    {
    ArrayList tempList = new ArrayList();
    foreach (PropertyInfo pi in propertys)
    {
    object obj = pi.GetValue(p_List[i], null);
    tempList.Add(obj);
    }
    object[] array = tempList.ToArray();
    _DataTable.LoadDataRow(array, true);
    }
    }
    result.Tables.Add(_DataTable);
    return result;
    }
    /// <summary>
    /// 泛型集合转换DataSet
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="list">泛型集合</param>
    /// <returns></returns>
    /// 2008-08-01 22:43 HPDV2806
    public static DataSet ToDataSet<T>(IList<T> list)
    {
    return ToDataSet<T>(list, null);
    }
    /// <summary>
    /// 泛型集合转换DataSet
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="p_List">泛型集合</param>
    /// <param name="p_PropertyName">待转换属性名数组</param>
    /// <returns></returns>
    /// 2008-08-01 22:44 HPDV2806
    public static DataSet ToDataSet<T>(IList<T> p_List, params string[] p_PropertyName)
    {
    List<string> propertyNameList = new List<string>();
    if (p_PropertyName != null)
    propertyNameList.AddRange(p_PropertyName);
    DataSet result = new DataSet();
    DataTable _DataTable = new DataTable();
    if (p_List.Count > 0)
    {
    PropertyInfo[] propertys = p_List[0].GetType().GetProperties();
    foreach (PropertyInfo pi in propertys)
    {
    if (propertyNameList.Count == 0)
    {
    // 没有指定属性的情况下全部属性都要转换
    _DataTable.Columns.Add(pi.Name, pi.PropertyType);
    }
    else
    {
    if (propertyNameList.Contains(pi.Name))
    _DataTable.Columns.Add(pi.Name, pi.PropertyType);
    }
    }
    for (int i = 0; i < p_List.Count; i++)
    {
    ArrayList tempList = new ArrayList();
    foreach (PropertyInfo pi in propertys)
    {
    if (propertyNameList.Count == 0)
    {
    object obj = pi.GetValue(p_List[i], null);
    tempList.Add(obj);
    }
    else
    {
    if (propertyNameList.Contains(pi.Name))
    {
    object obj = pi.GetValue(p_List[i], null);
    tempList.Add(obj);
    }
    }
    }
    object[] array = tempList.ToArray();
    _DataTable.LoadDataRow(array, true);
    }
    }
    result.Tables.Add(_DataTable);
    return result;
    }
    /// <summary>
    /// DataSet装换为泛型集合
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="p_DataSet">DataSet</param>
    /// <param name="p_TableIndex">待转换数据表索引</param>
    /// <returns></returns>
    /// 2008-08-01 22:46 HPDV2806
    public static IList<T> DataSetToIList<T>(DataSet p_DataSet, int p_TableIndex)
    {
    if (p_DataSet == null || p_DataSet.Tables.Count < 0)
    return null;
    if (p_TableIndex > p_DataSet.Tables.Count - 1)
    return null;
    if (p_TableIndex < 0)
    p_TableIndex = 0;
    DataTable p_Data = p_DataSet.Tables[p_TableIndex];
    // 返回值初始化
    IList<T> result = new List<T>();
    for (int j = 0; j < p_Data.Rows.Count; j++)
    {
    T _t = (T)Activator.CreateInstance(typeof(T));
    PropertyInfo[] propertys = _t.GetType().GetProperties();
    foreach (PropertyInfo pi in propertys)
    {
    for (int i = 0; i < p_Data.Columns.Count; i++)
    {
    // 属性与字段名称一致的进行赋值
    if (pi.Name.Equals(p_Data.Columns[i].ColumnName))
    {
    // 数据库NULL值单独处理
    if (p_Data.Rows[j][i] != DBNull.Value)
    pi.SetValue(_t, p_Data.Rows[j][i], null);
    else
    pi.SetValue(_t, null, null);
    break;
    }
    }
    }
    result.Add(_t);
    }
    return result;
    }
    /// <summary>
    /// DataSet装换为泛型集合
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="p_DataSet">DataSet</param>
    /// <param name="p_TableName">待转换数据表名称</param>
    /// <returns></returns>
    /// 2008-08-01 22:47 HPDV2806
    public static IList<T> DataSetToIList<T>(DataSet p_DataSet, string p_TableName)
    {
    int _TableIndex = 0;
    if (p_DataSet == null || p_DataSet.Tables.Count < 0)
    return null;
    if (string.IsNullOrEmpty(p_TableName))
    return null;
    for (int i = 0; i < p_DataSet.Tables.Count; i++)
    {
    // 获取Table名称在Tables集合中的索引值
    if (p_DataSet.Tables[i].TableName.Equals(p_TableName))
    {
    _TableIndex = i;
    break;
    }
    }
    return DataSetToIList<T>(p_DataSet, _TableIndex);
    }
    }

    在上面的SqlHelper中 增加如下方法直接获取List

       #region 返回一个List
    virtual public IList<T> SqlCe_ExecuteReturnListSql<T>(string selectSql)
    {
    try
    {
    var ds = SqlCe_ExecuteReturnDataSetSql(selectSql);

    var result = IListDataSet.DataSetToIList<T>(ds, 0);

    return result;

    }
    catch (Exception exception )
    {
    var i = exception;
    return null;
    }
    }
    #endregion

    使用方法很简单:



    View Code
                SqlHelper control = new SqlHelper("testDB.sdf",null);
    //var result = control.SqlCe_CreateDataBase();

    var ds = control.SqlCe_ExecuteReturnDataSetSql("select * from t");

    var list = control.SqlCe_ExecuteReturnListSql<testField>("select * from t");

    至此,WINCE系统操作本地数据已经解决,很羞愧其中没什么自己原创的东西,主要解决方案都是网上找的,不过解决问题之后,这就变成了我们自己的方法,这就是我们学习的过程不是么:)




  • 相关阅读:
    词汇小助手V1.0——一款跨平台词频统计和外语学习工具
    穿越狙击V1.0
    词汇小助手V1.4——加入单词测试功能
    词汇小助手V1.2——可以显示英语单词的国际音标
    词汇小助手官方网站发布了
    强大的云存储与应用管理工具DzzOffice1.0 Beta(大桌子办公)发布下载 大桌子
    <!DOCTYPE>前加有<! xxx >注释在IE中引发的bug
    去笔试腾讯的前端实习生,题目太尼玛坑爹了
    IE中的布局BUG和一些可以避开的BUG
    removeClass,addClass的原生JS代码
  • 原文地址:https://www.cnblogs.com/vinnie520/p/2373501.html
Copyright © 2011-2022 走看看