首页 > 代码库 > 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");

这两行代码是客户端能获取服务器上数据的关键,客户端与服务器调用相同的函数,通过返回值类型,客户端就能够从服务器上得到返回的数据。

 

 

最终运行结果如下: