ICE学习第四步-----客户端请求服务器返回数据

时间:2024-03-14 19:34:07

这次我们来做一个例子,流程很简单:客户端向服务器发送一条指令,服务端接收到这条指令之后,向客户端发送数据库中查询到的数据,最终显示在DataGridView上。

根据上一篇文章介绍的Slice语法,我们先来定义ICE文件。我定义两个ICE文件,一个用来描述测试数据库表中属性相关信息,另一个则是请求数据的方法。

结构如下:

   ICE学习第四步-----客户端请求服务器返回数据  ICE学习第四步-----客户端请求服务器返回数据

定义结构体,和数据库中表的列对应,添加序列(相当于数组类型)。

在获取表的方法中注意要记得#include带有结构的ice文件,并把接口函数的返回值类型写成之前定义的数组类型,否则就像HelloWorld例子中只能在服务器显示,调回不到客户端了。(DbTableDataSeq getDataFromDb(string requestCode);这个方法其实就是客户端一调用,然后服务器操作完成,最后返回DbTableDataSeq类型的数据)

 

编译ICE文件:

ICE学习第四步-----客户端请求服务器返回数据

 

在数据库中随便插入几条数据:

ICE学习第四步-----客户端请求服务器返回数据

 

之后是一系列基本工作:创建工程,添加对ICE的引用,拖入编译好的文件,对具有接口函数的ICE文件创建实现类,实现抽象类DoSelectTableDisp_

大体结构如下图:                  

ICE学习第四步-----客户端请求服务器返回数据

为了结构能更清晰,我们把它改成这样,同时添加上查询数据库的方法:

ICE学习第四步-----客户端请求服务器返回数据

给出这几个类的代码如下:

 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 DbDataList
15     {
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.database
10 {
11     public class Db2:DbMain
12     {
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 = new List<DbData>();
29                         for (int j = 0; j < dt.Columns.Count; j++)
30                         {
31                             DbData data = new DbData();
32                             data.dataName = dt.Columns[j].ColumnName;
33                             data.dataValue = 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 DbMain
10     {
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;)

ICE学习第四步-----客户端请求服务器返回数据

 

但是这并不是我们想要的返回类型,我们再将其转换为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.slice2csI
10 {
11     class TestTableMethodI:DoSelectTableDisp_
12     {
13         public static List<DbTableData> tbData = 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             else
24             {
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 = 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 Program
10     {
11         static void Main(string[] args)
12         {
13             int status = 0;
14             Ice.Communicator ic = null;
15             try
16             {
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             finally
31             {
32                 if (ic != null)
33                 {
34                     ic.destroy();
35                 }
36             }
37             Environment.Exit(status); 
38         }
39     }
40 }

如此一来服务端代码就写好了。

很少用BD2数据库,一直用SqlServer编译时报了如下警告,不能运行:

ICE学习第四步-----客户端请求服务器返回数据

在网上搜索了一下:改成了.NET Framwork4,没有后面的Client Profile,就可以用了;这个修改需要右击项目,然后选择其中的属性。

 

接下来我们编写客户端代码:

与服务端相同一开始是一系列基本工作:创建工程,添加对ICE的引用,拖入编译好的文件

大体结构如下图:

ICE学习第四步-----客户端请求服务器返回数据 

在Form上添加三个控件:

ICE学习第四步-----客户端请求服务器返回数据

给出完整客户端代码:

 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 FormCli
12 {
13     public partial class Form1 : Form
14     {
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             try
25             {
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             finally
71             {
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");

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

 

 

最终运行结果如下:

ICE学习第四步-----客户端请求服务器返回数据