RFID技术已经得到了广泛应用。比如门禁系统、车辆入库出库都会有RFID读写设备在工作。其原理简单讲就是,读写器向自己的有效区域发射信号,RFID标签会反射信号,读写器就读到了标签的信息。
RFID标签主要有4部分组成,分别是保留内存区、EPC、TID,和用户自定义存储区。其结构图如下:
ref:四个区详细内容介绍
我们打算在JT-8290A读写器和配套通讯协议基础上基于Socket技术做一个Windows小程序。(只是读EPC区,不涉及其他区)
开发工具:Visual Studio 2013
数据库:5.5.43 MySQL Community Server (GPL)
需要掌握的基础:WPF概念,基本sql语句,后面可能用到多线程、泛型、Socket等。
工作场景:RFID标签贴到设备或物资上,物资进出的时候会被读写器扫描到,扫描记录需要存储,库存记录也需要存储,在此基础上设计出如下的数据库。
图1-1 数据库结构图
People、type比较简单。
tags存储标签的EPC区信息和备注。
device表中typeName和tag字段是外键,repository表中tagID是外键,具体指向见图1-1
设备进出历史iohistory中tagID也是外键,这里方便测试将这个外键删掉了。。
项目源码以及MysqlHelper.cs和MysqlData.dll等文件在(http://pan.baidu.com/s/1qWqKe5Y)的CSharp目录下
数据库增删改查肯定是要实现的,先实现“查”功能……
新建infoShow.xaml文件,在Canvas标签下添加如下代码
<Canvas Grid.Row="2"> <TabControl Canvas.Left="10" Canvas.Top="5" Height="297" Width="658"> <TabItem Header="所有标签"> <Grid Background="AliceBlue"> <DataGrid AutoGenerateColumns="True" Height="Auto" Width="Auto" Margin="10,10,0,0" Name="dataGrid1" HorizontalAlignment="Left" VerticalAlignment="Top" IsReadOnly="True"/> </Grid> </TabItem> <TabItem Header="所有设备"></TabItem> <TabItem Header="所有人员"></TabItem> <TabItem Header="库存记录"></TabItem> <TabItem Header="进出历史"></TabItem> <TabItem Header="类别查看"></TabItem> </TabControl> </Canvas>
对应的infoShow.xaml.cs
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Diagnostics; using System.Data; namespace Ex03_DeviceMS_wpf { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { string connectionString = "Database='databaseName';Data Source='localhost';User Id='uid';Password='password';charset='utf8';pooling=true"; public MainWindow() { InitializeComponent(); MySqlHelper.Conn = connectionString; this.GetData(); } private void GetData() { string cmd = "select * from tb_tags"; DataSet ds = MySqlHelper.GetDataSet(MySqlHelper.Conn, CommandType.Text, cmd, null); this.dataGrid1.ItemsSource = ds.Tables[0].DefaultView; this.dataGrid1.AutoGenerateColumns = true;//自动 } } }
其他TabItem下,显示其他表格的方法与之类似。
增删改查功能(ref:wpf datagrid应用)
//添加如下Namespace using MySql.Data; using MySql.Data.MySqlClient; using System.Data; using System.Collections; using System.Configuration; namespace Ex02_wifiServer { /// <summary> ///MYSQLHelper 的摘要说明 /// </summary> public abstract class MySqlHelper { //数据库连接字符串 public static string Conn { get; set; } // 用于缓存参数的HASH表 private static Hashtable parmCache = Hashtable.Synchronized(new Hashtable()); /// <summary> /// 给定连接的数据库用假设参数执行一个sql命令(不返回数据集) /// </summary> /// <param name="connectionString">一个有效的连接字符串</param> /// <param name="cmdType">命令类型(存储过程, 文本, 等等)</param> /// <param name="cmdText">存储过程名称或者sql命令语句</param> /// <param name="commandParameters">执行命令所用参数的集合</param> /// <returns>执行命令所影响的行数</returns> public static int ExecuteNonQuery(string connectionString, CommandType cmdType, string cmdText, params MySqlParameter[] commandParameters) { MySqlCommand cmd = new MySqlCommand(); using (MySqlConnection conn = new MySqlConnection(connectionString)) { PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters); int val = cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); return val; } } /// <summary> /// 用现有的数据库连接执行一个sql命令(不返回数据集) /// </summary> /// <param name="connection">一个现有的数据库连接</param> /// <param name="cmdType">命令类型(存储过程, 文本, 等等)</param> /// <param name="cmdText">存储过程名称或者sql命令语句</param> /// <param name="commandParameters">执行命令所用参数的集合</param> /// <returns>执行命令所影响的行数</returns> public static int ExecuteNonQuery(MySqlConnection connection, CommandType cmdType, string cmdText, params MySqlParameter[] commandParameters) { MySqlCommand cmd = new MySqlCommand(); PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters); int val = cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); return val; } /// <summary> ///使用现有的SQL事务执行一个sql命令(不返回数据集) /// </summary> /// <remarks> ///举例: /// int result = ExecuteNonQuery(connString, CommandType.StoredProcedure, "PublishOrders", new MySqlParameter("@prodid", 24)); /// </remarks> /// <param name="trans">一个现有的事务</param> /// <param name="cmdType">命令类型(存储过程, 文本, 等等)</param> /// <param name="cmdText">存储过程名称或者sql命令语句</param> /// <param name="commandParameters">执行命令所用参数的集合</param> /// <returns>执行命令所影响的行数</returns> public static int ExecuteNonQuery(MySqlTransaction trans, CommandType cmdType, string cmdText, params MySqlParameter[] commandParameters) { MySqlCommand cmd = new MySqlCommand(); PrepareCommand(cmd, trans.Connection, trans, cmdType, cmdText, commandParameters); int val = cmd.ExecuteNonQuery(); cmd.Parameters.Clear(); return val; } /// <summary> /// 用执行的数据库连接执行一个返回数据集的sql命令 /// </summary> /// <remarks> /// 举例: /// MySqlDataReader r = ExecuteReader(connString, CommandType.StoredProcedure, "PublishOrders", new MySqlParameter("@prodid", 24)); /// </remarks> /// <param name="connectionString">一个有效的连接字符串</param> /// <param name="cmdType">命令类型(存储过程, 文本, 等等)</param> /// <param name="cmdText">存储过程名称或者sql命令语句</param> /// <param name="commandParameters">执行命令所用参数的集合</param> /// <returns>包含结果的读取器</returns> public static MySqlDataReader ExecuteReader(string connectionString, CommandType cmdType, string cmdText, params MySqlParameter[] commandParameters) { //创建一个MySqlCommand对象 MySqlCommand cmd = new MySqlCommand(); //创建一个MySqlConnection对象 MySqlConnection conn = new MySqlConnection(connectionString); //在这里我们用一个try/catch结构执行sql文本命令/存储过程,因为如果这个方法产生一个异常我们要关闭连接,因为没有读取器存在, //因此commandBehaviour.CloseConnection 就不会执行 try { //调用 PrepareCommand 方法,对 MySqlCommand 对象设置参数 PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters); //调用 MySqlCommand 的 ExecuteReader 方法 MySqlDataReader reader = cmd.ExecuteReader(CommandBehavior.CloseConnection); //清除参数 cmd.Parameters.Clear(); return reader; } catch { //关闭连接,抛出异常 conn.Close(); throw; } } /// <summary> /// 返回DataSet /// </summary> /// <param name="connectionString">一个有效的连接字符串</param> /// <param name="cmdType">命令类型(存储过程, 文本, 等等)</param> /// <param name="cmdText">存储过程名称或者sql命令语句</param> /// <param name="commandParameters">执行命令所用参数的集合</param> /// <returns></returns> public static DataSet GetDataSet(string connectionString, CommandType cmdType, string cmdText, params MySqlParameter[] commandParameters) { //创建一个MySqlCommand对象 MySqlCommand cmd = new MySqlCommand(); //创建一个MySqlConnection对象 MySqlConnection conn = new MySqlConnection(connectionString); //在这里我们用一个try/catch结构执行sql文本命令/存储过程,因为如果这个方法产生一个异常我们要关闭连接,因为没有读取器存在, try { //调用 PrepareCommand 方法,对 MySqlCommand 对象设置参数 PrepareCommand(cmd, conn, null, cmdType, cmdText, commandParameters); //调用 MySqlCommand 的 ExecuteReader 方法 MySqlDataAdapter adapter = new MySqlDataAdapter(); adapter.SelectCommand = cmd; DataSet ds = new DataSet(); adapter.Fill(ds); //清除参数 cmd.Parameters.Clear(); conn.Close(); return ds; } catch (Exception e) { throw e; } } /// <summary> /// 用指定的数据库连接字符串执行一个命令并返回一个数据集的第一列 /// </summary> /// <remarks> ///例如: /// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new MySqlParameter("@prodid", 24)); /// </remarks> ///<param name="connectionString">一个有效的连接字符串</param> /// <param name="cmdType">命令类型(存储过程, 文本, 等等)</param> /// <param name="cmdText">存储过程名称或者sql命令语句</param> /// <param name="commandParameters">执行命令所用参数的集合</param> /// <returns>用 Convert.To{Type}把类型转换为想要的 </returns> public static object ExecuteScalar(string connectionString, CommandType cmdType, string cmdText, params MySqlParameter[] commandParameters) { MySqlCommand cmd = new MySqlCommand(); using (MySqlConnection connection = new MySqlConnection(connectionString)) { PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters); object val = cmd.ExecuteScalar(); cmd.Parameters.Clear(); return val; } } /// <summary> /// 用指定的数据库连接执行一个命令并返回一个数据集的第一列 /// </summary> /// <remarks> /// 例如: /// Object obj = ExecuteScalar(connString, CommandType.StoredProcedure, "PublishOrders", new MySqlParameter("@prodid", 24)); /// </remarks> /// <param name="connection">一个存在的数据库连接</param> /// <param name="cmdType">命令类型(存储过程, 文本, 等等)</param> /// <param name="cmdText">存储过程名称或者sql命令语句</param> /// <param name="commandParameters">执行命令所用参数的集合</param> /// <returns>用 Convert.To{Type}把类型转换为想要的 </returns> public static object ExecuteScalar(MySqlConnection connection, CommandType cmdType, string cmdText, params MySqlParameter[] commandParameters) { MySqlCommand cmd = new MySqlCommand(); PrepareCommand(cmd, connection, null, cmdType, cmdText, commandParameters); object val = cmd.ExecuteScalar(); cmd.Parameters.Clear(); return val; } /// <summary> /// 将参数集合添加到缓存 /// </summary> /// <param name="cacheKey">添加到缓存的变量</param> /// <param name="commandParameters">一个将要添加到缓存的sql参数集合</param> public static void CacheParameters(string cacheKey, params MySqlParameter[] commandParameters) { parmCache[cacheKey] = commandParameters; } /// <summary> /// 找回缓存参数集合 /// </summary> /// <param name="cacheKey">用于找回参数的关键字</param> /// <returns>缓存的参数集合</returns> public static MySqlParameter[] GetCachedParameters(string cacheKey) { MySqlParameter[] cachedParms = (MySqlParameter[])parmCache[cacheKey]; if (cachedParms == null) return null; MySqlParameter[] clonedParms = new MySqlParameter[cachedParms.Length]; for (int i = 0, j = cachedParms.Length; i < j; i++) clonedParms[i] = (MySqlParameter)((ICloneable)cachedParms[i]).Clone(); return clonedParms; } /// <summary> /// 准备执行一个命令 /// </summary> /// <param name="cmd">sql命令</param> /// <param name="conn">OleDb连接</param> /// <param name="trans">OleDb事务</param> /// <param name="cmdType">命令类型例如 存储过程或者文本</param> /// <param name="cmdText">命令文本,例如:Select * from Products</param> /// <param name="cmdParms">执行命令的参数</param> private static void PrepareCommand(MySqlCommand cmd, MySqlConnection conn, MySqlTransaction trans, CommandType cmdType, string cmdText, MySqlParameter[] cmdParms) { if (conn.State != ConnectionState.Open) conn.Open(); cmd.Connection = conn; cmd.CommandText = cmdText; if (trans != null) cmd.Transaction = trans; cmd.CommandType = cmdType; if (cmdParms != null) { foreach (MySqlParameter parm in cmdParms) cmd.Parameters.Add(parm); } } } }
[1] Karli Wastson. C#入门经典(第6版)[M].