首页 > 代码库 > .NET通过RFC读取SAP数据

.NET通过RFC读取SAP数据

  本篇文章中我主要讲的是.NET如何通过RFC从SAP中读取数据。为了功能的可复用性,我将调用RFC的代码从业务层中分离出来单独建立在一个namespace中。

  当然除了需要我们自己编写代码以外,还需要引用SAP提供的程序集文件(sapnco.dll、sapnco_utils.dll),在代码文件需要引用相应的命名空间(using SAP.Middleware.Connector;)。

  我在这个namespace中建立了三个类来实现这个功能,一个配置类(RfcDestinationConfig)、一个参数类(RfcParam)、一个主体功能类(RfcManager)。

  • RfcDestinationConfig

  我们需要一个类来实现SAP的连接配置工作,就如同为数据连接层建立一个数据库配置类一样重要。

 1 public class RfcDestinationConfig : IDestinationConfiguration
 2     {
 3         #region 事件
 4         /// <summary>
 5         /// 配置变更事件
 6         /// </summary>
 7         public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
 8         /// <summary>
 9         /// 默认接收器名称
10         /// </summary>
11         public static readonly string DefaultDesName = "destination";
12         #endregion
13 
14         #region 方法
15         /// <summary>
16         /// 配置变更事件触发时,暂时无用
17         /// </summary>
18         /// <param name="destinationName"></param>
19         /// <param name="args"></param>
20         public void OnConfigurationChanged(string destinationName, RfcConfigurationEventArgs args)
21         {
22             if (ConfigurationChanged != null)
23             {
24                 ConfigurationChanged(destinationName, args);
25             }
26         }
27 
28         /// <summary>
29         /// 获取SAP配置参数
30         /// </summary>
31         /// <param name="destinationName"></param>
32         /// <returns></returns>
33         public RfcConfigParameters GetParameters(string destinationName)
34         {
35             if (destinationName == DefaultDesName)
36             {
37                 RfcConfigParameters parms = new RfcConfigParameters();
38                 parms.Add(RfcConfigParameters.AppServerHost,ConfigManager.GetAppSettings("SAPApplicationServer").Trim());   //SAP主机IP
39                 parms.Add(RfcConfigParameters.SystemNumber, ConfigManager.GetAppSettings("SAPSystemNumber").Trim());  //SAP实例
40                 parms.Add(RfcConfigParameters.User, ConfigManager.GetAppSettings("SAPUser").Trim());  //用户名
41                 parms.Add(RfcConfigParameters.Password,ConfigManager.GetAppSettings("SAPPwd").Trim());  //密码
42                 parms.Add(RfcConfigParameters.Client, ConfigManager.GetAppSettings("SAPClient").Trim());  // Client
43                 parms.Add(RfcConfigParameters.Language,ConfigManager.GetAppSettings("SAPLanguage").Trim());  //登陆语言
44                 return parms;
45             }
46             else
47             {
48                 return null;
49             }
50         }
51 
52         /// <summary>
53         /// 变更事件方法,暂时无用
54         /// </summary>
55         /// <returns>true</returns>
56         public bool ChangeEventsSupported()
57         {
58             return true;
59         }
60         #endregion
61     }
  • RfcParam

  想要从SAP中读取数据,就必须将查询条件作为参数传递给RFC。另外为了返回的结果具有通用性,我使用DataTable作为返回结果的类型,然后考虑到不同条件下列是不同的,我又将列也参数化,最终我将输入参数和输出参数都封装在一个参数类之中。

 1 public class RfcParam
 2     {
 3         /// <summary>
 4         /// 初始化
 5         /// </summary>
 6         public RfcParam()
 7         {
 8             CoulmnNames = new List<string>();
 9             Param = new Dictionary<string, object>();
10         }
11         /// <summary>
12         /// RFC方法名称
13         /// </summary>
14         public string RfcName { get; set; }
15         /// <summary>
16         /// RFC表名
17         /// </summary>
18         public string TableName { get; set; }
19         /// <summary>
20         /// 数据表各列的列名
21         /// </summary>
22         public List<string> CoulmnNames { get; set; }
23         /// <summary>
24         /// RFC执行参数
25         /// </summary>
26         public Dictionary<string, object> Param { get; set; }
27     }
  • RfcManager

  该主角登场了,读取数据的功能正是业务层真正想要的东西。

  方法ExecRfc首先将输出参数转换成一个真正可用的新的DataTable,然后将输入参数传递给SAP执行相关的RFC功能并返回IRfcTable(SAP定义的一种接口),最后再将IRfcTable转换成我们自定义的DataTable。

 1 public class RfcManager
 2     {
 3         #region 属性字段
 4         /// <summary>
 5         /// 接收器
 6         /// </summary>
 7         public RfcDestination Prd { get; set; }
 8         /// <summary>
 9         /// 数据仓库
10         /// </summary>
11         public RfcRepository Repo { get; set; }
12         #endregion
13 
14         #region 构造函数
15         /// <summary>
16         /// 初始化
17         /// </summary>
18         public RfcManager()
19         {
20             //初始化RFC接收器
21             //配置接收器
22             IDestinationConfiguration IDC = new RfcDestinationConfig();
23             //注册
24             RfcDestinationManager.RegisterDestinationConfiguration(IDC);
25             //获取RFC接收器
26             this.Prd = RfcDestinationManager.GetDestination(RfcDestinationConfig.DefaultDesName);
27             this.Repo = this.Prd.Repository;
28             //注销
29             RfcDestinationManager.UnregisterDestinationConfiguration(IDC);            
30         }
31         #endregion
32 
33         #region 方法
34         /// <summary>
35         /// 执行RFC获取数据表
36         /// </summary>
37         /// <param name="rfcname">rfc方法名称</param>
38         /// <param name="tablename">rfc表名</param>
39         /// <param name="columnnames">数据表列名列表</param>
40         /// <param name="param">rfc执行参数</param>
41         /// <returns>数据表</returns>
42         public DataTable ExecRfc(string rfcname, string tablename, List<string> columnnames, Dictionary<string, object> param)
43         {
44             DataTable dt = new DataTable();
45 
46             if (columnnames != null && columnnames.Count > 0)
47             {
48                 //配置datatable
49                 dt.Columns.Clear();
50                 foreach (string cname in columnnames)
51                 {
52                     dt.Columns.Add(cname, typeof(string));
53                 }
54                 dt.AcceptChanges();
55 
56                 //从SAP那获取数据表
57                 if (!string.IsNullOrEmpty(rfcname) && param != null && param.Count > 0)
58                 {
59                     IRfcFunction rfc = this.Repo.CreateFunction(rfcname);
60                     foreach (KeyValuePair<string, object> kv in param)
61                     {
62                         rfc.SetValue(kv.Key, kv.Value);
63                     }
64                     rfc.Invoke(this.Prd);
65                     IRfcTable iTable = rfc.GetTable(tablename);
66                     if (iTable.Count > 0)
67                     {
68                         for (int i = 0; i < iTable.RowCount; i++)
69                         {
70                             iTable.CurrentIndex = i;
71                             DataRow oNewRow = dt.NewRow();
72                             foreach (string cname in columnnames)
73                             {
74                                 oNewRow[cname] = iTable.GetString(cname).ToString();
75                             }
76                             dt.Rows.Add(oNewRow);
77                         }
78                     }
79                 }
80             }
81 
82             return dt;
83         }
84         #endregion
85     }