• .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     }
  • 相关阅读:
    我的CISSP备考之路
    【CISSP备考笔记】第8章:软件开发安全
    【CISSP备考笔记】第7章:安全运营
    【CISSP备考笔记】第6章:安全评估与测试
    【CISSP备考笔记】第5章 身份与访问管理
    【CISSP备考笔记】第4章:通信与网络安全
    【CISSP备考笔记】第3章:安全工程
    【CISSP备考笔记】第2章:资产安全
    【CISSP备考笔记】第1章:安全与风险管理
    PHP后门隐藏技巧
  • 原文地址:https://www.cnblogs.com/liusuqi/p/3745099.html
Copyright © 2020-2023  润新知