來源
C# SAP .Net Connector 3.0連接RFC示例
必備環境:
1,類庫sapnco.dll、sapnco_utils.dll。可以通過官方下載安裝取得,也可以直接從網上只下載這兩個類庫,還能直接從NuGet獲取:Install-Package SAPDotNetConnector3 -Version 0.3.0
。
2,Microsoft Visual C++ 2010 Redistributable Package,簡稱Microsoft Visual C++ 2010 。下載鏈接,可從控制面板查看已安裝程序確認有沒安裝。Windows更新中可能已包含了Microsoft Visual C++ 2010,但不在已安裝程序中顯示。
步驟1:SAP定義RFC
步驟2:C#實現
a):調用SAP RFC封裝類:
namespace RFCLib { //C#代碼創建Sap連接對象的類SapConnection public class SapConnection : IDestinationConfiguration { RfcConfigParameters IDestinationConfiguration.GetParameters(string destinationName) //或 public RfcConfigParameters GetParameters(string destinationName) { SAPClient sapClient; System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(SAPClient)); string sapClientSettingPath = System.AppDomain.CurrentDomain.BaseDirectory+ "SAPClientSetting.config"; using (System.IO.FileStream fileStream = new System.IO.FileStream(sapClientSettingPath, System.IO.FileMode.Open)) { sapClient = (SAPClient)serializer.Deserialize(fileStream); } return GetParameters(destinationName, sapClient); } public RfcConfigParameters GetParameters(string destinationName, SAPClient sapInfo) { RfcConfigParameters conf = new RfcConfigParameters(); if (destinationName == "NSP")//給連接SAP的對象命個名 { //先添加必填參數 conf.Add(RfcConfigParameters.SystemNumber, sapInfo.SystemNumber); //conf.Add(RfcConfigParameters.SystemID, ""); conf.Add(RfcConfigParameters.User, sapInfo.User); conf.Add(RfcConfigParameters.Password, sapInfo.Password); conf.Add(RfcConfigParameters.Client, sapInfo.Client); conf.Add(RfcConfigParameters.Language, sapInfo.Language); //添加可選參數(普通登陸參數) if (!string.IsNullOrEmpty(sapInfo.ApplicationServer)) conf.Add(RfcConfigParameters.AppServerHost, sapInfo.ApplicationServer); if (!string.IsNullOrEmpty(sapInfo.AppServerService)) conf.Add(RfcConfigParameters.AppServerService, sapInfo.AppServerService); //添加可選參數(服務器組參數) if (!string.IsNullOrEmpty(sapInfo.MessageServerHost)) conf.Add(RfcConfigParameters.MessageServerHost, sapInfo.MessageServerHost); if (!string.IsNullOrEmpty(sapInfo.MessageServerService)) conf.Add(RfcConfigParameters.MessageServerService, sapInfo.MessageServerService); if (!string.IsNullOrEmpty(sapInfo.LogonGroup)) conf.Add(RfcConfigParameters.LogonGroup, sapInfo.LogonGroup); if (!string.IsNullOrEmpty(sapInfo.SystemID)) conf.Add(RfcConfigParameters.SystemID, sapInfo.SystemID); } return conf; } public bool ChangeEventsSupported() { return true; } public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged; } //SAP連接參數類 public class SAPClient { public string ApplicationServer { get; set; } //應用服務器IP地址,如 10.88.88.88 public string AppServerService { get; set; } public string Client { get; set; } //sap客戶端 如 100 public string Language { get; set; } //語言,如 ZH 或 EN public string LogonGroup { get; set; } //登錄組名 public string MessageServerHost { get; set; } //消息服務器IP地址 public string MessageServerService { get; set; } public string Password { get; set; } //登錄密碼 public string SystemID { get; set; } //系統標識 public string SystemNumber { get; set; } //實例號,如 00 public string User { get; set; } //登錄賬號 } //自定義的調用RFC的類 public class NcoQueryRFC { //創建Sap連接對象的類SapConnection的實例global_dest,單例模式 private static RfcDestination global_dest; public static RfcDestination SapConnInfo() { if (global_dest == null) { //SapConnection類定義見代碼末 SapConnection con= new SapConnection(); RfcDestinationManager.RegisterDestinationConfiguration(con); } //這裏定義 global_dest = RfcDestinationManager.GetDestination("NSP"); return global_dest; } //查詢RFC的方法 //public static IRfcFunction ExcuteAndGetSAPFuntion(string funtionName,List<Dictionary<string,object>> functionparamsList) /// <summary> /// 調用RFC並獲取SAP函數調用結果 /// </summary> /// <param name="funtionName">函數名稱</param> /// <param name="functionparamsList">函數所需參數</param> /// <returns>RFC調用結果</returns> static IRfcFunction ExcuteAndGetSAPFuntion(string funtionName, List<Dictionary<string, object>> functionparamsList) { RfcDestination dest = NcoQueryRFC.SapConnInfo(); RfcRepository rfcrep = dest.Repository; IRfcFunction myfun = rfcrep.CreateFunction(funtionName); //RFC的名稱 foreach (Dictionary<string,Object> functionparams in functionparamsList) { foreach (var item in functionparams) { myfun.SetValue(item.Key, item.Value); } } myfun.Invoke(dest);//調用 return myfun;//直接返回function,取到的結果由調用者提取。 } //查詢RFC導出 public static Dictionary<string, object> GetRFCExport(string funtionName, List<Dictionary<string, object>> functionparamsList, List<string> exportParams) { Dictionary<string, object> exports = new Dictionary<string, object>(); IRfcFunction myfun = ExcuteAndGetSAPFuntion(funtionName,functionparamsList); //RFC的名稱 foreach (string exportParam in exportParams) { exports.Add(exportParam,myfun.GetValue(exportParam)); } return exports; } /// <summary> /// 調用RFC,獲取返回的table /// </summary> /// <param name="funtionName">函數名</param> /// <param name="functionparamsList">函數參數列表</param> /// <param name="tableName">RFC中定義的返回table的名稱</param> /// <returns></returns> public static IRfcTable GetRFCTable(string funtionName, List<Dictionary<string, object>> functionparamsList, string tableName) { Dictionary<string, object> exports = new Dictionary<string, object>(); IRfcFunction myfun = ExcuteAndGetSAPFuntion(funtionName, functionparamsList); //RFC的名稱 IRfcTable rfcTable = myfun.GetTable(tableName); return rfcTable; } } }
b):RFC返回Table轉.Net平臺DataTable對象。
/// <summary> /// 將RFC返回的Table轉換爲.Net平臺的DataTable對象 /// </summary> /// <param name="rfcTable">RFC返回Table</param> /// <returns>轉換後的.Net平臺DataTable對象</returns> DataTable GetRFCData(IRfcTable rfcTable) { DataTable sourceTable = new DataTable(); string columnName; //新增列 for (int i = 0; i < rfcTable.Metadata.LineType.FieldCount; i++) { columnName = rfcTable.Metadata[i].Name; sourceTable.Columns.Add(columnName); } DataRow row; //新增行 foreach (SAP.Middleware.Connector.IRfcStructure item in rfcTable) { row = sourceTable.NewRow(); string cellValue; for (int i = 0; i < rfcTable.Metadata.LineType.FieldCount; i++) { columnName = rfcTable.Metadata[i].Name; cellValue = item.GetString(columnName); //NUM類型,去除前導0 if (rfcTable.Metadata[i].DataType == RfcDataType.NUM ) { cellValue = Convert.ToInt32(item.GetString(columnName)).ToString(); } row[columnName] = cellValue; } sourceTable.Rows.Add(row); } return sourceTable; }
c):C#通過封裝類庫調用RFC
/// <summary> /// 從SAP根據料號及類別獲取SAP圖文檔類別、編號、版本、名稱 /// </summary> /// <param name="part">料號</param> /// <param name="sapDoctype">SAP類別代號</param> ///// <param name="code">返回結果狀態碼:0成功 1失敗</param> ///// <param name="msg">返回結果描述</param> /// <param name="result">返回結果</param> [WebMethod(Description = "從SAP根據料號及類別獲取圖文檔類別、編號、版本、名稱")] //public void GetPLMCADD_SAP(string part, string sapDoctype, ref string code,ref string msg, ref object result) public string GetPLMCADD_SAP(string part, string sapDoctype) { #region 初始返回對象與參數檢驗 SAPServiceResult sAPServiceResult = new SAPServiceResult() { Code = "1", Message = "未處理!", Data = null }; if (string.IsNullOrEmpty(part) || string.IsNullOrEmpty(sapDoctype)) { sAPServiceResult.Message = "缺少參數"; return Newtonsoft.Json.JsonConvert.SerializeObject(sAPServiceResult, Newtonsoft.Json.Formatting.Indented); } else if (!RFCLib.RFC.SAPDocTypes.Split(',').Contains(sapDoctype)) { sAPServiceResult.Message = $"類別{sapDoctype}不存在"; return Newtonsoft.Json.JsonConvert.SerializeObject(sAPServiceResult, Newtonsoft.Json.Formatting.Indented); } #endregion List<Dictionary<string, object>> paramsList = new List<Dictionary<string, object>>(); Dictionary<string, object> keyValuePairs2 = new Dictionary<string, object>() { { "IM_MATNR", part } }; paramsList.Add(keyValuePairs2); //1,通過料號獲取SAP圖文檔類別、編號、版本、名稱 string rfcTableName = RFCLib.RFC.sapRfcs.Where(x => x.Name == "ZPLM_MAT_LINK_DIRS_GET_MES").Take(1).Select(x => x.Table.Name).FirstOrDefault(); IRfcTable rfcTable = RFCLib.NcoQueryRFC.GetRFCTable("ZPLM_MAT_LINK_DIRS_GET_MES", paramsList, rfcTableName); DataTable ZPLM_MAT_LINK_DIRS_GET_TableData = GetRFCData(rfcTable); DataRow row1 = ZPLM_MAT_LINK_DIRS_GET_TableData.AsEnumerable().Where(x => x["DOKAR"].ToString() == sapDoctype.Trim()).OrderByDescending(x => x["DOKVR"]).FirstOrDefault(); object[] rowData = row1.ItemArray;//先將結果保存起來,否則Rows.Clear()後,row1會被清空。 ZPLM_MAT_LINK_DIRS_GET_TableData.Rows.Clear(); ZPLM_MAT_LINK_DIRS_GET_TableData.Rows.Add(rowData); sAPServiceResult.Code = "0"; sAPServiceResult.Message = "ok"; sAPServiceResult.Data = ZPLM_MAT_LINK_DIRS_GET_TableData; string jsonStr = Newtonsoft.Json.JsonConvert.SerializeObject(sAPServiceResult, Newtonsoft.Json.Formatting.Indented); return jsonStr; } /// <summary> /// SAPService接口返回封裝對象 /// </summary> class SAPServiceResult { /// <summary> /// 狀態碼:0執行成功,其他執行失敗 /// </summary> public string Code { get; set; } /// <summary> /// 說明 /// </summary> public string Message { get; set; } /// <summary> /// 執行結果 /// </summary> public object Data { get; set; } }