【问题标题】:cannot get function metadata since there is no metadata repository无法获取函数元数据,因为没有元数据存储库
【发布时间】:2018-05-23 10:26:38
【问题描述】:

我在开发 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>

如果此错误消息给任何人敲响了警钟:请分享您对如何解决它的见解。

【问题讨论】:

    标签: .net visual-studio sap


    【解决方案1】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-22
      • 2013-06-12
      • 1970-01-01
      • 2012-05-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多