首页 > 代码库 > ICE学习第四步-----客户端请求服务器返回数据
ICE学习第四步-----客户端请求服务器返回数据
这次我们来做一个例子,流程很简单:客户端向服务器发送一条指令,服务端接收到这条指令之后,向客户端发送数据库中查询到的数据,最终显示在DataGridView上。
根据上一篇文章介绍的Slice语法,我们先来定义ICE文件。我定义两个ICE文件,一个用来描述测试数据库表中属性相关信息,另一个则是请求数据的方法。
结构如下:
定义结构体,和数据库中表的列对应,添加序列(相当于数组类型)。
在获取表的方法中注意要记得#include带有结构的ice文件,并把接口函数的返回值类型写成之前定义的数组类型,否则就像HelloWorld例子中只能在服务器显示,调回不到客户端了。(DbTableDataSeq getDataFromDb(string requestCode);这个方法其实就是客户端一调用,然后服务器操作完成,最后返回DbTableDataSeq类型的数据)
编译ICE文件:
在数据库中随便插入几条数据:
之后是一系列基本工作:创建工程,添加对ICE的引用,拖入编译好的文件,对具有接口函数的ICE文件创建实现类,实现抽象类DoSelectTableDisp_
大体结构如下图:
为了结构能更清晰,我们把它改成这样,同时添加上查询数据库的方法:
给出这几个类的代码如下:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 6 namespace ConsoleSer.common 7 { 8 public class DbData 9 {10 public string dataName;//数据库中列名11 public object dataValue;//数据库中列值12 }13 14 public class DbDataList15 {16 public IList<DbData> dataRow;17 }18 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using ConsoleSer.common; 6 using IBM.Data.DB2; 7 using System.Data; 8 9 namespace ConsoleSer.database10 {11 public class Db2:DbMain12 {13 public override IList<DbDataList> GetDataFromDatabase(string strSql)14 {15 IList<DbDataList> list = new List<DbDataList>();16 17 using (DB2Connection con = new DB2Connection("server=127.0.0.1;database=TEST;uid=db2admin;pwd=db2admin;"))18 {19 con.Open();20 DB2DataAdapter oda = new DB2DataAdapter(strSql, con);21 DataSet ds = new DataSet();22 oda.Fill(ds);23 if (ds.Tables.Count > 0)24 {25 DataTable dt = ds.Tables[0];26 for (int i = 0; i < dt.Rows.Count; i++)27 {28 IList<DbData> rowsData = http://www.mamicode.com/new List<DbData>();29 for (int j = 0; j < dt.Columns.Count; j++)30 {31 DbData data = http://www.mamicode.com/new DbData();32 data.dataName = dt.Columns[j].ColumnName;33 data.dataValue =http://www.mamicode.com/ dt.Rows[i][data.dataName];34 rowsData.Add(data);35 }36 DbDataList rows = new DbDataList();37 rows.dataRow = rowsData;38 list.Add(rows);39 }40 }41 }42 return list;43 }44 }45 }
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using ConsoleSer.common; 6 7 namespace ConsoleSer.database 8 { 9 public class DbMain10 {11 public virtual IList<DbDataList> GetDataFromDatabase(string strSql)12 {13 IList<DbDataList> list = new List<DbDataList>();14 return list;15 }16 }17 }
最终查询完数据库返回的是这样的一条数据:(IList<DbDataList> list = new List<DbDataList>(); DbDataList包含两个字段string dataName;object dataValue;)
但是这并不是我们想要的返回类型,我们再将其转换为DbTableData类型数组,于是在TestTableMethodI实现类中有如下代码(假设客户端请求字符串是getTable):
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using tableStructFamily; 6 using ConsoleSer.common; 7 using ConsoleSer.database; 8 9 namespace ConsoleSer.slice2csI10 {11 class TestTableMethodI:DoSelectTableDisp_12 {13 public static List<DbTableData> tbData = http://www.mamicode.com/new List<DbTableData>();//数据库中表信息14 private static DbMain dbObject = new Db2();15 16 public override DbTableData[] getDataFromDb(string requestCode, Ice.Current current__)17 {18 if (requestCode == "getTable")19 {20 Console.WriteLine("收到请求!");21 return selectDataFromDb();22 }23 else24 {25 throw new Exception();26 }27 }28 29 private DbTableData[] selectDataFromDb()30 {31 IList<DbDataList> list = dbObject.GetDataFromDatabase("select * from A.T_test");32 33 DbTableData[] objs = new DbTableData[list.Count];34 35 for (int i = 0; i < list.Count; i++)36 {37 DbDataList row = list[i];38 DbTableData obj = GetTableObj(row);39 tbData.Add(obj);40 objs[i] = obj;41 }42 return objs;43 }44 45 private DbTableData GetTableObj(DbDataList dataRow)46 {47 DbTableData obj = new DbTableData();48 for (int i = 0; i < dataRow.dataRow.Count; i++)49 {50 DbData data =http://www.mamicode.com/ dataRow.dataRow[i];51 setObjValue(data, ref obj);52 }53 return obj;54 }55 56 private void setObjValue(DbData data, ref DbTableData obj)57 {58 string name = data.dataName.ToLower();59 switch (name)60 {61 case "id":62 obj.ID = Convert.ToInt32(data.dataValue);63 break;64 case "nname":65 obj.Nname = data.dataValue.ToString();66 break;67 default:68 break;69 }70 }71 }72 }
附上Main函数初始化ICE的方法:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using tableStructFamily; 6 7 namespace ConsoleTestIceServer 8 { 9 class Program10 {11 static void Main(string[] args)12 {13 int status = 0;14 Ice.Communicator ic = null;15 try16 {17 ic = Ice.Util.initialize(ref args);18 Ice.ObjectAdapter adapter = ic.createObjectAdapterWithEndpoints("tableSelector", "default -p 10000");19 Ice.Object obj = new ConsoleSer.slice2csI.TestTableMethodI();20 adapter.add(obj, Ice.Util.stringToIdentity("tableSelector"));21 adapter.activate();22 Console.WriteLine("初始化成功!");23 ic.waitForShutdown();24 }25 catch (Exception e)26 {27 Console.Error.WriteLine(e);28 status = 1;29 }30 finally31 {32 if (ic != null)33 {34 ic.destroy();35 }36 }37 Environment.Exit(status); 38 }39 }40 }
如此一来服务端代码就写好了。
很少用BD2数据库,一直用SqlServer编译时报了如下警告,不能运行:
在网上搜索了一下:改成了.NET Framwork4,没有后面的Client Profile,就可以用了;这个修改需要右击项目,然后选择其中的属性。
接下来我们编写客户端代码:
与服务端相同一开始是一系列基本工作:创建工程,添加对ICE的引用,拖入编译好的文件
大体结构如下图:
在Form上添加三个控件:
给出完整客户端代码:
1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Windows.Forms; 9 using tableStructFamily;10 11 namespace FormCli12 {13 public partial class Form1 : Form14 {15 public Form1()16 {17 InitializeComponent();18 }19 20 private void btnSendRequestCode_Click(object sender, EventArgs e)21 {22 int status = 0;23 Ice.Communicator ic = null;24 try25 {26 ic = Ice.Util.initialize();27 txtShowMsg.AppendText("初始化成功!\r\n");28 Ice.ObjectPrx obj = ic.stringToProxy("tableSelector:default -p 10000");29 DoSelectTablePrx selector = DoSelectTablePrxHelper.checkedCast(obj);30 if (selector == null)31 {32 throw new ApplicationException("Invalid proxy");33 }34 txtShowMsg.AppendText("开始发送请求!\r\n");35 DbTableData[] objs = selector.GetDataFromDb("getTable");36 txtShowMsg.AppendText("发送请求成功!\r\n");37 38 if (objs.Length > 0)39 {40 txtShowMsg.AppendText("成功获取数据!\r\n");41 }42 43 44 foreach (DbTableData td in objs)45 {46 txtShowMsg.AppendText(td.id.ToString() + "\r\n");47 txtShowMsg.AppendText(td.nName.ToString() + "\r\n");48 }49 50 DataTable dt = new DataTable();51 dt.Columns.Add("ID");52 dt.Columns.Add("Nname");53 foreach (DbTableData td in objs)54 {55 DataRow dr = dt.NewRow();56 dr["ID"] = td.id;57 dr["Nname"] = td.nName;58 dt.Rows.Add(dr);59 }60 61 dgvShowTable.DataSource = dt;62 63 //显示到gridview中64 }65 catch (Exception ex)66 {67 MessageBox.Show(ex.ToString());68 status = 1;69 }70 finally71 {72 if (ic != null)73 ic.destroy();74 }75 txtShowMsg.AppendText(status.ToString());76 //Environment.Exit(status);77 }78 79 }80 }
DoSelectTablePrx selector = DoSelectTablePrxHelper.checkedCast(obj);
DbTableData[] objs = selector.GetDataFromDb("getTable");
这两行代码是客户端能获取服务器上数据的关键,客户端与服务器调用相同的函数,通过返回值类型,客户端就能够从服务器上得到返回的数据。
最终运行结果如下: