由于没有元数据存储库,因此无法获取函数元数据

时间:2018-05-23 10:26:38

标签: .net visual-studio sap

我在开发SAP服务器时遇到以下错误+堆栈跟踪,我无法理解它,也无法找到任何有用信息的谷歌搜索结果:

  由于没有元数据存储库,

无法获取函数元数据

 at SAP.Middleware.Connector.ServerFunctionInfo.get_FunctionMetadata()
   at SAP.Middleware.Connector.RfcServer.InvokeServerFunction(RfcConnection conn, ServerFunctionInfo serverFuncInfo, RfcServerFunction functionImp)
   at SAP.Middleware.Connector.RfcServer.Dispatch(RfcConnection conn)
   at SAP.Middleware.Connector.RfcConnection.Dispatch()
   at SAP.Middleware.Connector.RfcTransaction.Playback()
   at SAP.Middleware.Connector.RfcServer.ARfcDestShipImp(RfcServerContext ctx, IRfcFunction func)

在我发现的一篇论坛帖子中,我读到它可能需要对权限做一些事情 - 但另一端说他给了我关于该测试系统的完全权限。所以这似乎不是它不起作用的原因。

代码失败,只要另一个端点尝试发送数据,并且在我的终端上调用服务器功能。这是我的代码:

SAP服务器工厂

public static class SapServerFactory
{
    private static readonly ConcurrentDictionary<string, SapServer> Servers = new ConcurrentDictionary<string, SapServer>();

    public static SapServer Create(string configurationName)
    {
        return Servers.GetOrAdd(configurationName.ToUpper(), CreateSapServer(configurationName));
    }

    private static SapServer CreateSapServer(string configurationName)
    {
        var server = RfcServerManager.GetServer(configurationName, new Type[] { typeof(RfcServerDelegate) });

        return new SapServer(server);
    }
}

服务器委托

// http://www.dataxstream.com/2011/08/nco-3-rfc-server-step-by-step/
public static class RfcServerDelegate
{
    public static event SapServerExecutionHandler ServerCalled;

    public delegate void SapServerExecutionHandler(RfcServerContext context, IRfcFunction function);

    [RfcServerFunction(Default = true)]
    public static void DefaultHandler(RfcServerContext context, IRfcFunction function)
    {
        ServerCalled?.Invoke(context, function);
    }
}

SAP服务器

public delegate void RfcServerHandler<T>(RfcServer server, T args);
public delegate void RfcServerFunctionHandler(RfcServer server, RfcServerContext context, IRfcFunction function);
public delegate void RfcTransactionIdHandler(RfcServerContextInfo context, RfcTID transactionId);
public delegate T RfcTransactionIdHandler<T>(RfcServerContextInfo context, RfcTID transactionId);

public class SapServer : IDisposable, ITransactionIDHandler
{
    public RfcServer Server { get; }

    public event RfcServerHandler<RfcServerState> StateChanged;
    public event RfcServerHandler<RfcServerErrorEventArgs> ApplicationError;
    public event RfcServerHandler<RfcServerErrorEventArgs> Error;
    public event RfcServerFunctionHandler FunctionCalled;

    public event RfcTransactionIdHandler<bool> CheckTransactionId;
    public event RfcTransactionIdHandler CommitTransactionId;
    public event RfcTransactionIdHandler ConfirmTransactionId;
    public event RfcTransactionIdHandler RollbackTransactionId;

    public SapServer(RfcServer server)
    {
        RfcServerDelegate.ServerCalled += RfcServerDelegateOnServerCalled;
        Server = server;
        Server.RfcServerStateChanged += ServerOnRfcServerStateChanged;
        Server.RfcServerApplicationError += ServerOnRfcServerApplicationError;
        Server.RfcServerError += ServerOnRfcServerError;
        Server.TransactionIDHandler = CreateDefaultTransactionHandler();
    }

    protected virtual ITransactionIDHandler GetDefaultTransactionHandler()
    {
        return this;
    }

    private ITransactionIDHandler CreateDefaultTransactionHandler()
    {
        return GetDefaultTransactionHandler();
    }

    private void RfcServerDelegateOnServerCalled(RfcServerContext context, IRfcFunction function)
    {
        if(context.Server == Server)
            FunctionCalled?.Invoke(Server, context, function);
    }

    private void ServerOnRfcServerError(object o, RfcServerErrorEventArgs args)
    {
        Error?.Invoke(o as RfcServer, args);
    }

    private void ServerOnRfcServerApplicationError(object o, RfcServerErrorEventArgs args)
    {
        ApplicationError?.Invoke(o as RfcServer, args);
    }

    private void ServerOnRfcServerStateChanged(object o, RfcServerStateChangedEventArgs args)
    {
        State = args.NewState;
        StateChanged?.Invoke(o as RfcServer, args.NewState);
    }

    public RfcServerState State { get; set; }

    private bool _firstStart = true;
    public void Start()
    {
        if (!State.In(RfcServerState.Starting, RfcServerState.Running) || _firstStart)
        {
            Server.Start();
            _firstStart = false;
        }
    }

    public void Stop(bool abortRunningCalls)
    {
        if (!State.In(RfcServerState.Stopped, RfcServerState.Stopping))
            Server.Shutdown(abortRunningCalls);
    }

    public void Dispose()
    {
        RfcServerDelegate.ServerCalled -= RfcServerDelegateOnServerCalled;
        Server.RfcServerStateChanged -= ServerOnRfcServerStateChanged;
        Server.RfcServerApplicationError -= ServerOnRfcServerApplicationError;
        Server.RfcServerError -= ServerOnRfcServerError;

        if(Server.TransactionIDHandler is IDisposable disposableTransactionHandler && !object.ReferenceEquals(disposableTransactionHandler, this))
        {
            disposableTransactionHandler.Dispose();
        }

        Server.TransactionIDHandler = null;
    }

    bool ITransactionIDHandler.CheckTransactionID(RfcServerContextInfo ctx, RfcTID tid)
    {
        if (CheckTransactionId == null)
            return true;

        foreach (var item in CheckTransactionId.GetInvocationList())
        {
            if (item is RfcTransactionIdHandler<bool> handler)
            {
                if (!handler.Invoke(ctx, tid))
                    return false;
            }
        }

        return true;
    }

    void ITransactionIDHandler.Commit(RfcServerContextInfo ctx, RfcTID tid)
    {
        CommitTransactionId?.Invoke(ctx, tid);
    }

    void ITransactionIDHandler.Rollback(RfcServerContextInfo ctx, RfcTID tid)
    {
        RollbackTransactionId?.Invoke(ctx, tid);
    }

    void ITransactionIDHandler.ConfirmTransactionID(RfcServerContextInfo ctx, RfcTID tid)
    {
        ConfirmTransactionId?.Invoke(ctx, tid);
    }
}

的app.config

<SAP.Middleware.Connector>
    <ServerSettings>
        <ServerConfiguration>
            <servers>
                <add NAME="somename" 
                     GWHOST="some.domain.com" 
                     GWSERV="somepassword"
                     PROGRAM_ID="someprogramid"
                     REG_COUNT="1" />
    </servers>
  </ServerConfiguration>
</ServerSettings>
<ClientSettings>
  <DestinationConfiguration>
    <destinations>
      <add NAME="SapDestination1"
                     SYSNR="42"
                     USER="someuser"
                     PASSWD="somepassword"
                     LANG="EN" 
                     CLIENT="011" 
                     ASHOST="somehostname"  />
            </destinations>
        </DestinationConfiguration>
    </ClientSettings>
</SAP.Middleware.Connector>

如果此错误消息对任何人发出响铃:请分享您对如何解决问题的见解。

1 个答案:

答案 0 :(得分:0)

问题隐藏在内部异常中 - 服务器条目需要“REPOSITORY_DESTINATION”并且登录详细信息不正确。