当前位置: 代码迷 >> SAP >> .NET透过RFC读取SAP数据
  详细解决方案

.NET透过RFC读取SAP数据

热度:1124   发布时间:2016-04-29 01:47:30.0
.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         #endregion13 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主机IP39                 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());  // Client43                 parms.Add(RfcConfigParameters.Language,ConfigManager.GetAppSettings("SAPLanguage").Trim());  //登陆语言44                 return parms;45             }46             else47             {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         #endregion61     }
  • 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         #endregion13 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         #endregion32 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                 //配置datatable49                 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         #endregion85     }

 

 

2楼HHSYHLL
我一开始看别人用VB写的连接类,看着不习惯,就想用C#写,结果到这句就不行了,MyConnection.CodePage = quot;8300quot;,c#的SDK没有这个属性,不用这个属性,拉下来的数据就乱码,服务器数据是繁体#183;#183;#183;
1楼阿水
顶一记,以前做过类似接口用C#不行用VB行,好像是涉及到强类型的问题。
Re: 浪花一朵朵
@阿水,早期版本确实如此,现在用C#可以了
  相关解决方案