设为首页 收藏本站
查看: 8749|回复: 1

[经验分享] 转博客园一位前辈关于.NET通过NCO3.0连接SAP的系列文章

[复制链接]
累计签到:6 天
连续签到:1 天
发表于 2015-9-19 02:00:17 | 显示全部楼层 |阅读模式
  NET连接SAP系统专题:.NET调用RFC几种方式(一)
  本来今天是要写一篇关于NCO3.0的东西,就是关乎.NET调用SAP的RFC的,支持VS2010和.NET 4.0等。现在网上到处都是充斥着NCO1.X和NCO2.0,需要用VS2003来使用,都是一些没什么大用的东西,连.NET 2.0的不能支持,只能算是废材一个。而且相关的资料非常的少,转来转去全部都是那么一个例子,丝毫没有直观的DEMO,更搞笑的是SAP里面的RFC是怎么建立的都没有说明,只有该死的C#代码。同时还有微软发布的Data Provider for mySAP Business Suite这个,开始用的时候觉得还挺有趣,后来试了一下很失望,抓出来的字段居然是断码,不知道是我不懂还是怎么的。同时更让人无语的是用它的话还必须要导入一个Request NO,加入一个自定义的Function才可以使用Data Provider for mySAP Business Suite,很脑残也很不靠谱。
  后来发现NCO3.0也发布了,和以前的版本大不相同。后面试用了一下NCO3.0,效果很好。
  公司有几只程序,是在台湾SAP端运行程序,自动下载品号等信息至厦门的SQL Server数据库供OA使用的,每次要用到的品号都需要去SAP系统运行那个程序。虽然Basis设置了4个小时执行一次,但是还是有些过慢。我就想着如果能在OA这边用NCO3.0,然后调用SAP的RFC,就自动下载所需要的品号那就非常方便了。我在030也试用了一下,很OK!
  既然.NET能够和SAP互相通信,在RFC里就可以任意发挥了,想做什么就做什么。这样可以免去SAP系统的账户成本压力。
  呵呵,下篇博文开始介绍一下NCO3.0这个东西。


.NET连接SAP系统专题:SAP中新建可远程调用的RFC(二)

分类: SAP顾问进行时 2011-08-22 22:34 2001人阅读 评论(0) 收藏 举报

    何谓RFC,就是一个Function,可以被非SAP系统调用,比如VB,C#,Java等。如果我们在RFC中INCLUDE了相关的业务逻辑,那么我们就可以完全操控SAP中的业务数据了。就像在TTE里,有一只程序,前端是在OA开发,设计了相关的客户提领库存,然后还要到SAP系统中去执行程序扣减相应的库存,这样是挺费劲的,如果能够在OA中放一个按钮,点击这个按钮就自动执行了这个程序,方便省事。而这一切,可以利用C#调用RFC来实现。

    要实现整个过程,则必须要现在SAP中建立好相应的RFC函数,然后用VS建立好相应的程序,写代码调用就可以了。两者关联就是使用NCO3.0这个东西了。

    OK,本节主要讲在SAP中建立我们想要的RFC出来。

    那么,我们假定要实现这样的一个功能:运行在SAP系统外的一个程序窗体,上面有一个下拉框和文本框。程序运行之后自动载入SAP中某个Client的品号至该下拉框,用户只要点击了这个下拉框,内容一改变,则旁边的文本框就现实该品号的品名出来。够简单吧!

    首先登陆SAP,比如我们要操作的Client为888(我自己建立的,图个吉利)。运行SE37:

      

      然后:

      

      建立函数组,输入相关内容:

      

     完了点击保存。

     之后回到SE37,输入我们要调用的RFC函数名,比如:ZRFC_MARA_INFO  然后点击新建(右一按钮):

     

     点击保存之后会弹出如下对话框:

   

    点击打勾,忽略之。

    主画面如下:

   

     画面切换至 属性 页,设置该RFC为可远程调用。

     

      因为我们到时候会传递一个品号进来读取品名,SO,在Import页面设置一个参数用来传递进来品号:

     

     第一个复选框代表此参数可选可不选传递,第二个代表参考。在RFC里如果不打勾,保存会提示:

     

     因为我们会要抓取品名,需要有一个栏位抛出品名出来。SO,Export页面如下:

     

      因为我们程序一开始需要抛出所有的品号表格出来,SO,此时我们需要有一个内表专门用于抛出品号信息。Table属性页如下:

     

     至此,所有参数设置完毕。接下去就要去代码页编写相应的代码了。

     代码如下:

      SELECT * INTO CORRESPONDING FIELDS OF TABLE IT_MARA FROM MARA.

      SELECT SINGLE MAKTX INTO MAKTX FROM MAKT WHERE MATNR = MATNR AND SPRAS = '1'.

      

      最后点击激活!这里的激活不是单单激活这个RFC这么简单,还有其他的项目,记得要勾选上:      


     至此,RFC建立完毕。

     接下去就是在C#中调用它咯,下篇博文放出!


  .NET连接SAP系统专题:C#调用RFC代码(三)
分类: SAP顾问进行时 2011-08-22 22:34 2259人阅读 评论(0) 收藏 举报

  本文就说明在C#中如何编写代码来调用SAP中的RFC函数获取数据。(Winform32)
  首先需要引用两个NCO3.0的DLL,下载地址在文后。
  然后在程序代码页面引用:
  using SAP.Middleware.Connector;
  然后所有的代码如下:
  namespace SAP_RFC
  {
  public partial class Form1 : Form
  {
  string MATNR = string.Empty;
  public Form1()
  {
  InitializeComponent();
  }
  public void nco()
  {
  IDestinationConfiguration ID = new MyBackendConfig();
  RfcDestinationManager.RegisterDestinationConfiguration(ID);
  RfcDestination prd = RfcDestinationManager.GetDestination("PRD_000");
  RfcDestinationManager.UnregisterDestinationConfiguration(ID);
  nco(prd);
  }
  public void nco(RfcDestination prd)
  {            
  RfcRepository repo = prd.Repository;
  IRfcFunction companyBapi = repo.CreateFunction("ZRFC_MARA_INFO");   //调用函数名
  companyBapi.SetValue("MATNR", MATNR);   //设置Import的参数
  companyBapi.Invoke(prd);   //执行函数
  IRfcTable table = companyBapi.GetTable("IT_MARA");  //获取相应的品号内表
  string MAKTX = companyBapi.GetValue("MAKTX").ToString();  //获取品名
  DataTable dt = new DataTable();  //新建表格
  dt.Columns.Add("品号");  //表格添加一列
  for (int i = 0; i < table.RowCount; i++)
  {
  table.CurrentIndex = i;  //当前内表的索引行
  DataRow dr = dt.NewRow();
  dr[0] = table.GetString("MATNR");  //获取表格的某行某列的值
  dt.Rows.Add(dr);  //填充该表格的值
  }
  if (MATNR == "")
  {
  for (int i = 0; i < dt.Rows.Count; i++)
  {
  this.comboBox1.Items.Add(dt.Rows[0].ToString());   //填充下拉框
  }
  }
  this.label1.Text = MAKTX;   //显示品名
  prd = null;
  repo = null;
  }
  //登陆SAP前的准备工作
  public class MyBackendConfig : IDestinationConfiguration
  {
  public RfcConfigParameters GetParameters(String destinationName)
  {
  if ("PRD_000".Equals(destinationName))
  {
  RfcConfigParameters parms = new RfcConfigParameters();
  parms.Add(RfcConfigParameters.AppServerHost, "192.168.1.3");   //SAP主机IP
  parms.Add(RfcConfigParameters.SystemNumber, "00");  //SAP实例
  parms.Add(RfcConfigParameters.User, "MENGXIN");  //用户名
  parms.Add(RfcConfigParameters.Password, "5239898");  //密码
  parms.Add(RfcConfigParameters.Client, "888");  // Client
  parms.Add(RfcConfigParameters.Language, "ZH");  //登陆语言
  parms.Add(RfcConfigParameters.PoolSize, "5");
  parms.Add(RfcConfigParameters.MaxPoolSize, "10");
  parms.Add(RfcConfigParameters.IdleTimeout, "60");
  return parms;
  }
  else return null;
  }
  public bool ChangeEventsSupported()
  {
  return false;
  }
  public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
  }
  private void Form1_Load(object sender, EventArgs e)
  {
  comboBox1.Items.Clear();
  nco();
  comboBox1.SelectedIndex = 1;
  }
  //当下拉框索引变化的时候传递品号进去查询出品名出来
  private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
  {
  MATNR = comboBox1.Text.ToString();
  nco();
  }
  }
  }
  我想这个C#代码很简单,我就不多做详细说明了。结果如下:
  
  SAP中品号信息如下:
  
  由此可见数据完全OK,调用成功。
  程序在第一次载入的时候有点慢,在链接SAP和登陆。后续在下拉框变化的时候就立马显示出品名出来了,丝毫没有任何停顿。第二次链接SAP的时候大概是不必在登陆了,SAP系统中已有登陆信息,运行T-CODE:SM04
  
  红色框中这两个即是我们的RFC调用所留下的登录会话。一旦我们的C#程序退出之后,这两个RFC也就退出了。
  如果我们的C#程序是ASP.NET的话,页面关闭之后这个RFC登录信息都还在的。除非IIS关闭,否则只有等到SAP系统超时退出这两个登陆会话了。
  DLL下载地址:
  http://files.cnblogs.com/mengxin523/SAP_DotNetConnector3.zip
  
  
  .NET连接SAP系统专题:获取RFC中自定义的异常(四)
分类: SAP顾问进行时 2011-08-22 22:35 1850人阅读 评论(0) 收藏 举报

  有的时候我们需要在RFC中抛出一些自定义的异常,比如输入一个不存在的品号,我们需要抛出一个异常,告知用户品号不存在。有一个笨笨的做法就是通过返回值来判断,但是这样不灵活,同时也会因为品号不存在而继续之行RFC。如果我们能自己抛出异常,程序自动停止执行RFC,那将是两全其美!
  现在设定一个功能:输入两个数,第一个数除以第二个数。2个异常:被除数不能为0和除数不能为100。
  首先,在SE37中建立一个RFC,就用上篇博文的RFC吧。
  在IMPORT页设置如下:     
  
  Export页面设置如下:   
  
  Changing和Table页面放空
  Exceptions页面设置如下:   
  
  然后就是源码咯:     
  
  代码中,RAISE专门用于抛出异常,程序自动停止执行,所有的返回值将被清空!RAISE 后面的内容就是在Exceptions中定义的内容了。
  然后程序记得激活!!如此SAP端设置就结束了。
  回到VS2010中,新建一个程序,界面如下:     
  
  于是,开始写程序:
  首先是引用两个dll(参考上篇),并在程序开头输入:
  using SAP.Middleware.Connector;
  public void nco()
  {
  IDestinationConfiguration ID = new MyBackendConfig();
  RfcDestinationManager.RegisterDestinationConfiguration(ID);
  RfcDestination prd = RfcDestinationManager.GetDestination("PRD_000");
  RfcDestinationManager.UnregisterDestinationConfiguration(ID);   //反注册
  nco(prd);
  }
  public void nco(RfcDestination prd)
  {
  string type = string.Empty;
  RfcRepository repo = prd.Repository;
  IRfcFunction companyBapi = repo.CreateFunction("ZRFC_MARA_INFO");  //指定RFC名称
  try
  {
  companyBapi.SetValue("NUM1", textBox1.Text.Trim());  //输入参数复制
  companyBapi.SetValue("NUM2", textBox2.Text.Trim());  //输入参数复制
  companyBapi.Invoke(prd);  //开始调用执行
  textBox3.Text = companyBapi.GetValue("NUM3").ToString();  //获取返回结果
  }
  catch (RfcAbapException ex)  //此Exception专门用于获取用户自定义的异常信息!!!!
  {
  // companyBapi.Metadata.GetAbapException(ex.Key).Documentation   获取对应的异常的说明文字
  MessageBox.Show(companyBapi.Metadata.GetAbapException(ex.Key).Documentation, "SAP RFC返回信息", MessageBoxButtons.OK, MessageBoxIcon.Error);
  }
  catch (RfcTypeConversionException ex)  //此Exception专门用于获取变量类型转换的异常!!!!
  {
  MessageBox.Show("您输入的不是数值", "SAP RFC返回信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  }
  catch (RfcAbapRuntimeException ex)   //此Exception专门用于获取RFC执行过程中的运行时异常!!!!
  {
  MessageBox.Show(companyBapi.Metadata.GetAbapException(ex.Key).Documentation, "SAP RFC返回信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  }
  catch (RfcBaseException ex)  //此Exception是总Exception类,可以获取所有的异常,如果有多个Catch,则不可以放第一位!!!!
  {
  MessageBox.Show("其他所有错误", "SAP RFC返回信息", MessageBoxButtons.OK, MessageBoxIcon.Warning);
  }
  prd = null;
  repo = null;
  }
  public class MyBackendConfig : IDestinationConfiguration
  {
  public RfcConfigParameters GetParameters(String destinationName)
  {
  if ("PRD_000".Equals(destinationName))
  {
  RfcConfigParameters parms = new RfcConfigParameters();
  parms.Add(RfcConfigParameters.AppServerHost, "192.168.1.3");
  parms.Add(RfcConfigParameters.SystemNumber, "00");
  parms.Add(RfcConfigParameters.User, "MENGXIN");
  parms.Add(RfcConfigParameters.Password, "5239898");
  parms.Add(RfcConfigParameters.Client, "888");
  parms.Add(RfcConfigParameters.Language, "ZH");
  parms.Add(RfcConfigParameters.PoolSize, "5");
  parms.Add(RfcConfigParameters.MaxPoolSize, "10");
  parms.Add(RfcConfigParameters.IdleTimeout, "60");
  return parms;
  }
  else return null;
  }
  public bool ChangeEventsSupported()
  {
  return false;
  }
  public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
  }
  private void button1_Click(object sender, EventArgs e)
  {
  nco();
  }
  如此,C#运行结果如下:
  
  
  
  
  
  以上可以正确得出我们自己抛出的异常的信息出来。程序测试OK!!!
  
  
  .NET连接SAP系统专题:C#(NCO3)调用BAPI(五)
分类: SAP顾问进行时 2011-08-22 22:35 1636人阅读 评论(0) 收藏 举报

  周六加班,翻看以前写OA程序的时候无意中发现了当初的一个案子,就是让用户现在OA上申请一个SAP用户,然后提交给相关人员审核,通过之后直接在SAP中生成这个用户,不必在登陆到SAP中请系统管理员来做了。至于这一步,当然是使用BAPI来实现了,不可能对用户表进行新增数据,这样少了很多的关联表和一些逻辑判断,会是一场灾难。
  前几篇讲的都是C#去调用RFC的东西,既然BAPI也是属于RFC,如果标准的勾选了那个remote的话,那按道理来说是应该可以实现调用的了。但难点是BAPI里面很多的参数都是引用结构的,而不是单纯的string和int的类型,这点有点困难。在C#中翻看了NCO3是否有相关的结构类,可惜,都没有!
  查看了一下相关内容,发现几乎没有任何调用BAPI的例子,看来使用NCO3的人极少。
  只能自力更生了,还好,经过很严密的思考和尝试,终于实现了在C#中调用BAPI去实现录入业务数据了。我尝试的就是用BAPI_USER_CREATE这个BAPI,通过它可以新增一个用户。
  那么,相关内容和代码说明,就在下篇博文放出吧!
  
  
  .NET连接SAP系统专题:NCO3调用BAPI的一些说明(六)
分类: SAP顾问进行时 2011-08-24 22:46 1647人阅读 评论(0) 收藏 举报

  既然BAPI是一些特殊的RFC,封装了业务逻辑,使得将业务都变成一个一个对象,使用者只需要传入传出参数就可以了。
  NCO3连接BAPI之前先来看看BAPI的一些参数规则。我们以 BAPI_USER_CREATE 为例子。此BAPI调用了可以生成一个用户,它当然不是仅仅对USR02进行写入那么简单。生成之后该账户什么权限也没有。
  输入T-CODE:BAPI,然后在第二个页签下找到该BAPI:
  
  上图中的红色框框里就是我们要调用的BAPI的名称。双击它,进入到该BAPI的一些说明里:
  
  看到了,在属性页里它勾选了Remote... 说明它是可以远程操控的!
  
  上图里,注意到红色框框都是不可选的,也就是后面的复选框没有选中,它告诉我们,在调用BAPI的时候这些参数是必须要有值传进来的!
  
  这个就是返回的参数。当然,这个Return也是必须要传出来的值。
  细心的人从上面几个图片可以看出,“参考打印”栏位里都是BAPI开头的结构,或者是结构里面的一个字段。双击这些结构进去就可以看到相关的栏位组成。
  现在回到Import页签里,双击USERNAME的“参考打印”——BAPIBNAME-BAPIBNAME。“-”前部分是结构,后面是这个结构里的一个栏位。进入到里面:
  
  这个BAPINAME结构只有一个栏位,而且是CHAR型,12码,SO,在传 用户名 进来的时候就是写入字符串即可。
  我们看看PASSWORD,对应的结构是:BAPIPWD 双击之,如下图:
  
  发现这里面只有一个栏位,CHAR型,40码,传密码之用。
  再看看ADDRESS栏位对应的结构BAPIADDR3,双击之:
  
  这个结构栏位就比较多了。虽然这里没有规定那些是必须要有值的,但确实有些是需要赋值,有些则可以放空。
  我们在SU01里面新建用户的时候系统会提示要求输入姓和名,那么这里的FIRSTNAME和LASTNAME是必须的了。
  BAPI里传入的参数LOGONDATA是放登陆数据的,具体的结构不再赘述。而返回的信息RETURN里有一个MESSAGE是放调用结果的信息,我们在NCO3里调用要用到它来返回结果信息。
  知道了这些原理之后就很清楚知道在C#中要怎么写了,那些参数是必须的就一目了然了。SO,下篇博文放出NCO3调用BAPI的代码!
  
  NET连接SAP系统专题:NCO3调用BAPI的代码(七)
分类: SAP顾问进行时 2011-08-25 22:43 1598人阅读 评论(0) 收藏 举报

  上面博文可知BAPI_USER_CREATE的一些结构和参数。所以在C#中要调用它就很清楚了要输入哪些参数了。
  1、首先引用dll,然后在程序开头:using SAP.Middleware.Connector;
  2、接下去就是设置登陆参数了,以前相关博文都有说明:
  public class MyBackendConfig : IDestinationConfiguration
  {
  public RfcConfigParameters GetParameters(String destinationName)
  {
  if ("PRD_000".Equals(destinationName))
  {
  RfcConfigParameters parms = new RfcConfigParameters();
  parms.Add(RfcConfigParameters.AppServerHost, "192.168.1.3");
  parms.Add(RfcConfigParameters.SystemNumber, "00");
  parms.Add(RfcConfigParameters.User, "MENGXIN");
  parms.Add(RfcConfigParameters.Password, "5239898");
  parms.Add(RfcConfigParameters.Client, "888");
  parms.Add(RfcConfigParameters.Language, "ZH");
  parms.Add(RfcConfigParameters.PoolSize, "5");
  parms.Add(RfcConfigParameters.MaxPoolSize, "10");
  parms.Add(RfcConfigParameters.IdleTimeout, "60");
  return parms;
  }
  else return null;
  }
  public bool ChangeEventsSupported()
  {
  return false;
  }
  public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
  }
  3、设置一个方法,引用这个登陆参数的类:
  public void nco()
  {
  IDestinationConfiguration ID = new MyBackendConfig();
  RfcDestinationManager.RegisterDestinationConfiguration(ID);
  RfcDestination prd = RfcDestinationManager.GetDestination("PRD_000");
  RfcDestinationManager.UnregisterDestinationConfiguration(ID);
  nco(prd);
  }
  4、然后就是开始了调用代码,以下代码全部放出,然后一行一行说明:
  public void nco(RfcDestination prd)
  {
  //选择要调用的BAPI的名称
  RfcFunctionMetadata BAPI_COMPANYCODE_GETDETAIL_MD = prd.Repository.GetFunctionMetadata("BAPI_USER_CREATE");
  //新建调用该BAPI的一个“实例”
  IRfcFunction function = null;
  function = BAPI_COMPANYCODE_GETDETAIL_MD.CreateFunction();
  //因为用户名称是一个字段,所以直接赋予字符串即可
  function.SetValue("USERNAME", USERID.Text.Trim());
  //接下去是密码。因为密码是一个结构,该结构只有一个栏位,所以这里先获取这个密码结构
  IRfcStructure PWD = function.GetStructure("PASSWORD");
  //设置这个结构中的这个栏位的内容
  PWD.SetValue("BAPIPWD", password.Text.Trim());
  //再把这个结构传进去给作为密码参数
  function.SetValue("PASSWORD", PWD);
  //这个是登陆信息,类型也是一个结构,所以这里获取出这个登录信息的结构出来
  IRfcStructure logo = function.GetStructure("LOGONDATA");
  //以下两个是设置这个登陆结构的一些栏位的值
  logo.SetValue("GLTGV", "20110821");
  logo.SetValue("GLTGB", "99991231");
  //将登陆信息的结构传进去给LOGONDATA
  function.SetValue("LOGONDATA", logo);   //设置参数
  //这个是地址信息,取结构,然后赋值,再将它传进去
  IRfcStructure address = function.GetStructure("ADDRESS");
  address.SetValue("FIRSTNAME", firstname.Text.Trim());
  address.SetValue("LASTNAME", lastname.Text.Trim());
  address.SetValue("DEPARTMENT", "资讯室");
  function.SetValue("ADDRESS", address);   //设置参数
  //以下这个DEFAULTS是账户的默认信息,不是必须要的。我们这里利用它设置登入账户的语言为ZH
  IRfcStructure DEFAULTS = function.GetStructure("DEFAULTS");
  DEFAULTS.SetValue("LANGU", "1"); //语言代码,对应简体中文!
  function.SetValue("DEFAULTS", DEFAULTS);
  //以下这个是RETURN,是回传结果的结构。记住,这里跟上面不一样,上面是Structure,这里则是Table!!
  IRfcTable returnStructure = function.GetTable("RETURN");
  function.Invoke(prd);//提交调用BAPI   
  //弹出对话框显示调用结果
  MessageBox.Show(returnStructure.GetString("MESSAGE").ToString());            
  prd = null;
  }
  5、程序运行结果如下:
  
  
  6、登陆到SAP,运行SU01,输入IT_XM01,看看结果:
  
  
  
  当然,如果该用户已经存在了你还去调用这个BAPI生成用户,系统会很知趣的提示:
  
  使用IT_XM01登陆系统,一切OK,系统状态如下:
  
  新建的账户一点权限也没有的,此时可以调用其他BAPI对其新增权限!!方法大同小异,这里不再详述。
  
  .NET连接SAP系统专题:C#调用BAPI给账户赋予权限(八)
分类: SAP顾问进行时 2011-08-28 11:23 1678人阅读 评论(0) 收藏 举报

  接上篇博文。
  上篇博文讲到C#调用BAPI BAPI_USER_CREATE 来生成SAP账户,但是新建的账户一点权限也没有,现在我们就再次利用BAPI给账户授予权限。
  首先,我们在BAPI画面里查找出相关的BAPI出来,利用角色去给用户添加权限:
  
  双击此BAPI,进入到BAPI预览画面:
  
  Table属性页:
  
  第一个ACTIVITYGROUPS是指我们要传进去的表格内容,不再是一个栏位和结构内容了。第二个的RETURN则是返回调用结果。
  双击BAPIAGR的结构,进入结构详情画面:
  
  以上AGR_NAME是角色名,应该是必须要的。
  那么,接下去就是在C#中编写相应的代码来调用它了。
  1、首先引用dll,然后在程序开头:using SAP.Middleware.Connector;
  2、接下去就是设置登陆参数了,以前相关博文都有说明:
  public class MyBackendConfig : IDestinationConfiguration
  {
  public RfcConfigParameters GetParameters(String destinationName)
  {
  if ("PRD_000".Equals(destinationName))
  {
  RfcConfigParameters parms = new RfcConfigParameters();
  parms.Add(RfcConfigParameters.AppServerHost, "192.168.1.3");
  parms.Add(RfcConfigParameters.SystemNumber, "00");
  parms.Add(RfcConfigParameters.User, "MENGXIN");
  parms.Add(RfcConfigParameters.Password, "5239898");
  parms.Add(RfcConfigParameters.Client, "888");
  parms.Add(RfcConfigParameters.Language, "ZH");
  parms.Add(RfcConfigParameters.PoolSize, "5");
  parms.Add(RfcConfigParameters.MaxPoolSize, "10");
  parms.Add(RfcConfigParameters.IdleTimeout, "60");
  return parms;
  }
  else return null;
  }
  public bool ChangeEventsSupported()
  {
  return false;
  }
  public event RfcDestinationManager.ConfigurationChangeHandler ConfigurationChanged;
  }
  3、设置一个方法,引用这个登陆参数的类:
  public void nco()
  {
  IDestinationConfiguration ID = new MyBackendConfig();
  RfcDestinationManager.RegisterDestinationConfiguration(ID);
  RfcDestination prd = RfcDestinationManager.GetDestination("PRD_000");
  RfcDestinationManager.UnregisterDestinationConfiguration(ID);
  nco(prd);
  }
  4、然后就是开始了调用代码,以下代码全部放出,然后一行一行说明:
  public void nco(RfcDestination prd)
  {
  //调用BAPI
  RfcFunctionMetadata BAPI_COMPANYCODE_GETDETAIL_MD = prd.Repository.GetFunctionMetadata("BAPI_USER_ACTGROUPS_ASSIGN");
  IRfcFunction function = null;
  function = BAPI_COMPANYCODE_GETDETAIL_MD.CreateFunction();
  //传入我们要赋予权限的用户名
  function.SetValue("USERNAME", USERID.Text.Trim());
  //接下去就是传入角色名。由于ACTIVITYGROUPS 是在Table属性页,所以我们是用Table 而不是Import和Export属性页里面用的Structure
  IRfcTable ROFTable = function.GetTable("ACTIVITYGROUPS");
  //上面语句产生的ROFTable 其实是一张空表,里面除了有那几个栏位之外是没有任何记录的,所以在对表格赋值之前需要先进性新增一行
  ROFTable .Insert();
  //接下去就是对表格当前行的相关栏位赋值。如下的角色名“MIS”是预选在SAP中建立好的
  ROFTable .CurrentRow.SetValue("AGR_NAME", "MIS");
  ROFTable .CurrentRow.SetValue("FROM_DAT", "20110825");
  ROFTable .CurrentRow.SetValue("TO_DAT", "99991231");
  //传入该赋值后的表格
  function.SetValue("ACTIVITYGROUPS", ROFTable);
  //引用回传结果
  IRfcTable RETURNStructure = function.GetTable("RETURN");
  //提交调用         
  function.Invoke(prd);
  //显示调用结果
  MessageBox.Show(RETURNStructure.GetString("MESSAGE").ToString());
  prd = null;
  }
  5、调用结果如下:
  
  
  
  如此则此用户已经赋予相应的权限了,运行所有T-CODE,没问题!
  对了,如果要赋予多个角色的话,那么就是多做ROFTable.Insert();然后再做相应赋值即可。
  
  PS:C#调用RFC系列专题就到此告一段落了,如果读者有建议或者疑问欢迎交流指正~!
  
  .NET连接SAP系统专题:sapnco.dll在ASP.NET中载入失败的解决方法(九)
分类: SAP顾问进行时 2011-11-21 16:51 1646人阅读 评论(0) 收藏 举报

  当所有一切代码准备就绪之后,如果是ASP.NET那就是要发布网站到服务器了。如果服务器上的系统是WIN2003,那很不幸,系统会提示这样的“红脸”过来:
  
  意思是说sapnco_utils.dll和sapnco.dll这两个文件不能载入。
  Could not load file or assembly "sapnco_utils,Version=3.0.0.42,...
  网上查找了方法也不尽然,各说纷纭。但是在WIN2008下的IIS7跟WinXP下的IIS5.1都可以完全正常,但是这个WIN2003就不行。
  后来在对这两个DLL进行分析的时候发现它们是用VC++2005开发的,想到WIN2003系统可能没有必要的运行库。于是在工作站测试的时候安装了VC++2005 32bit版,然后刷新一切就正常了!
  解决方法:安装相应vc++2005运行库即可!(实践证明:VC++2008不行!)
  附VC++2005 32位运行库下载地址:
  http://files.cnblogs.com/mengxin523/vcredist2005sp1_x86_XiaZaiBa.zip
  
  .NET连接SAP系统专题:BAPI_TRANSACTION_COMMIT的使用方法(十)
分类: SAP顾问进行时 2011-11-21 16:52 1518人阅读 评论(1) 收藏 举报

  为什么.net调用SAP的BAPI接口需要调用BAPI_TRANSACTION_COMMIT呢?首先得明白BAPI_TRANSACTION_COMMIT这个BAPI的作用。它功劳很大,在SAP里面很多的BAPI直接调用是不会有结果的,因为需要COMMIT一下才能生效,比如生成资产编号的BAPI:BAPI_FIXEDASSET_CREATE1,如果对他直接在SE37中调用运行或者使用SE38调用它,虽然可以得到一个资产编号,但是在AS03里面查询,系统会很白痴得提示你:该资产编号不存在于XX公司。更搞的是当你在AS01中新建资产编号时,新建的资产编号会跳过之前用BAPI生成“失败”的号码。
  那么,这就需要COMMIT一下,在调用这个BAPI之后再紧接调用BAPI_TRANSACTION_COMMIT这个。但是,在SE38中是可以这样做,而在.net中就没那么简单了,直接在调用完BAPI_FIXEDASSET_CREATE1之后再紧接调用BAPI_TRANSACTION_COMMIT是不可以的,虽然还是生成了资产编号,但仍旧是个废号。跟在SE37中调用无异。
  怎么在.net中解决这个问题呢,这就需要用到RfcSessionManager.BeginContext和RfcSessionManager.EndContext这两个方法了。只有在这两个方法之间调用BAPI才能方保万无一失!
  代码如下:
  1、首先引用:using SAP.Middleware.Connector;
  2、调用代码:
  public void nco(DataSet ds)
{
IDestinationConfiguration ID = new RfcConfig();
RfcDestinationManager.RegisterDestinationConfiguration(ID);
RfcDestination prd = RfcDestinationManager.GetDestination("PRD_000");
RfcDestinationManager.UnregisterDestinationConfiguration(ID);
nco(prd, ds);
}
public void nco(RfcDestination prd, DataSet ds)
{
bool asset = false;
//选择要调用的BAPI的名称
RfcFunctionMetadata BAPI_COMPANYCODE_GETDETAIL_MD = prd.Repository.GetFunctionMetadata("BAPI_REQUISITION_CREATE");
//新建调用该BAPI的一个“实例”
IRfcFunction function = null;
function = BAPI_COMPANYCODE_GETDETAIL_MD.CreateFunction();
IRfcTable ITEMS = function.GetTable("REQUISITION_ITEMS");
IRfcTable ACCOUNT = function.GetTable("REQUISITION_ACCOUNT_ASSIGNMENT");
IRfcTable RETURN = function.GetTable("RETURN");
int j = 0;
RfcSessionManager.BeginContext(prd);  //因期间需要同一个时间调用BAPI,而且各个BAPI之间有顺序关联,所以最好用这个包围起来
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
ITEMS.Insert();
j = j + 1;
j = j * 10;
ITEMS.CurrentRow.SetValue("PREQ_ITEM", j.ToString());
ITEMS.CurrentRow.SetValue("PREQ_NAME", ds.Tables[0].Rows["QGA27"].ToString());
ITEMS.CurrentRow.SetValue("CREATED_BY", ds.Tables[0].Rows["QGA27"].ToString());
ITEMS.CurrentRow.SetValue("PREQ_DATE", Convert.ToDateTime(ds.Tables[0].Rows["QGA15"].ToString()).Date);
ITEMS.CurrentRow.SetValue("MATERIAL", ds.Tables[0].Rows["QGA04"].ToString());
ITEMS.CurrentRow.SetValue("SHORT_TEXT", ds.Tables[0].Rows["QGA05"].ToString());
ITEMS.CurrentRow.SetValue("PLANT", "1201");
ITEMS.CurrentRow.SetValue("QUANTITY", Convert.ToDecimal(ds.Tables[0].Rows["QGA07"].ToString()));
ITEMS.CurrentRow.SetValue("DELIV_DATE", Convert.ToDateTime(ds.Tables[0].Rows["QGA09"].ToString()).Date);
ITEMS.CurrentRow.SetValue("C_AMT_BAPI", Convert.ToDecimal(ds.Tables[0].Rows["QGA14"].ToString()));
ITEMS.CurrentRow.SetValue("ACCTASSCAT", ds.Tables[0].Rows["QGA12"].ToString());
ITEMS.CurrentRow.SetValue("DOC_TYPE", ds.Tables[0].Rows["QGA28"].ToString());
ITEMS.CurrentRow.SetValue("UNIT", ds.Tables[0].Rows["QGA06"].ToString());
  ACCOUNT.Insert();
ACCOUNT.CurrentRow.SetValue("PREQ_ITEM", j.ToString());
ACCOUNT.CurrentRow.SetValue("COST_CTR", ds.Tables[0].Rows["QGA31"].ToString());
ACCOUNT.CurrentRow.SetValue("ORDER_NO", ds.Tables[0].Rows["QGA10"].ToString());
  if (ds.Tables[0].Rows["QGA12"].ToString().Trim() == "A")  //如果类别是A,即资产,则需要资产编号
{
ACCOUNT.CurrentRow.SetValue("ASSET_NO", GetASSET(prd, i, ds));  //设置新建的资产编号
ACCOUNT.CurrentRow.SetValue("CO_AREA", "1000");
ACCOUNT.CurrentRow.SetValue("SUB_NUMBER", "0000");
}
}
function.SetValue("REQUISITION_ITEMS", ITEMS);
function.SetValue("REQUISITION_ACCOUNT_ASSIGNMENT", ACCOUNT);
function.Invoke(prd);//提交调用BAPI
RfcSessionManager.EndContext(prd);
if (RETURN.GetString("TYPE").ToString().Trim() == "I")
{
Suess.Text = RETURN.GetString("MESSAGE").ToString();
BANFN.Text = "返回的请购单号:" + function.GetString("NUMBER").Trim();
}
else if (RETURN.GetString("TYPE").ToString().Trim() == "E")
{
Error.Text = RETURN.GetString("MESSAGE").ToString();
}
prd = null;
}
/// <summary>
/// 取得资产编号
/// </summary>
/// <param name="prd"></param>
/// <returns></returns>
public string GetASSET(RfcDestination prd, int i, DataSet ds)
{
RfcFunctionMetadata BAPI_COMPANYCODE_GETDETAIL_MD = prd.Repository.GetFunctionMetadata("BAPI_FIXEDASSET_CREATE1");
IRfcFunction function = null;
function = BAPI_COMPANYCODE_GETDETAIL_MD.CreateFunction();
IRfcStructure KEY = function.GetStructure("KEY");
KEY.SetValue("COMPANYCODE", "2012");
IRfcStructure GENERALDATA = function.GetStructure("GENERALDATA");
GENERALDATA.SetValue("ASSETCLASS", "00005990");
GENERALDATA.SetValue("DESCRIPT", ds.Tables[0].Rows["QGA05"].ToString());
IRfcStructure GENERALDATAX = function.GetStructure("GENERALDATAX");
GENERALDATAX.SetValue("ASSETCLASS", "X");
GENERALDATAX.SetValue("DESCRIPT", "X");
function.SetValue("KEY", KEY);
function.SetValue("GENERALDATA", GENERALDATA);
function.SetValue("GENERALDATAX", GENERALDATAX);
prd.Repository.ClearFunctionMetadata();  //貌似这句可以省略...
RfcFunctionMetadata BAPI_COMPANYCODE_GETDETAIL_MD1 = prd.Repository.GetFunctionMetadata("BAPI_TRANSACTION_COMMIT");
IRfcFunction function1 = null;
function1 = BAPI_COMPANYCODE_GETDETAIL_MD1.CreateFunction();
function1.SetValue("WAIT", "X");
RfcSessionManager.BeginContext(prd);
function.Invoke(prd);     //提交调用BAPI_FIXEDASSET_CREATE1  生成资产编号
function1.Invoke(prd);   //提交调用BAPI_TRANSACTION_COMMIT 进行COMMIT一下
RfcSessionManager.EndContext(prd);
twMsgbox.AjaxAlert(function.GetValue("ASSET").ToString().Trim());
return function.GetValue("ASSET").ToString().Trim();
}
  新建立之后的请购单一切OK,同时,建立的资产编号在AS03已经可以认出来了!!
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-115530-1-1.html 上篇帖子: PI-webservice05-SAP调用外部webservice 下篇帖子: SAP Useful Transaction Codes
累计签到:1 天
连续签到:1 天
发表于 2017-7-31 14:40:41 | 显示全部楼层
怎么看不到图片

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表