Can anyone help with the following problem?
The problem seems to be related to how the .NET Connector converts numbers internally to strings. Somehow, even though every DLL is defined to require the 1.1 framework, there is some internal SAP component which seems to use something in the 2.0 Framework. There is nothing wrong with the input data (we have spent many hours checking this). It is just 2.0 is stricter about conversions from strings to numbers I suspect.
If I install both 1.1 and 2.0 the error occurs. If I then uninstall 2.0 the error goes away. I do not even need to reboot my PC.
I think I have forced the application DLLs to use the 1.1 framework (I added an App.Config to each file with the lines)
<?xml version="1.0" encoding="utf-8" ?>
<supportedRuntime version="v1.1.4322" />
<requiredRuntime imageVersion="v1.1.4322" version="v1.1.4322" />
Correct me if i'm wrong..
So within this forum, you asked:
1. how do you convert the number?
2. why do you get error after installation?
For the answer,
1. Yes right, you have to make the type of the parameter in .NET equals with the SAP one when you are doing synchronization.
So in .NET, you can use function <b>convert</b>, to convert the parameter that you want to pass to SAP.
For ex [in VB]:
Dim a as integer = 9
Dim b as string = ""
b = convert.ToString(a)
2. If you wanna install .Net framework, make sure you have to install .Net with version 1.1 first then you go on version 2.0.
<b>* reward point if it helps you. </b>
Thanks for the reply, but I think this problem is more complicated.
Attached is a stack trace of the error. Note that sometimes it can execute the (SCM) BAPI CreateFromTemplate successfully but then will fail with a similar error on the (SCM)BAPI ChangePeggingMultiple. It works with 100% reliability in 1.1. It fails if 2.0 is installed (even if 1.1 is still installed). We have tried every trick we can think of to try to force Microsoft to use 1.1 when running this application but no luck. If we uninstall the 2.0 Framework the application starts to work again (we do not even need to restart the PC as far as I recall).
System.ArgumentException: Object of type 'System.String' cannot be converted to type 'System.Double'.
at System.RuntimeType.CheckValue(Object value, Binder binder, CultureInfo culture, BindingFlags invokeAttr)
at System.Reflection.MethodBase.CheckArguments(Object parameters, Binder binder, BindingFlags invokeAttr, CultureInfo culture, Signature sig)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean skipVisibilityChecks)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, BindingFlags invokeAttr, Binder binder, Object index, CultureInfo culture)
at System.Reflection.RuntimePropertyInfo.SetValue(Object obj, Object value, Object index)
at SAP.Connector.Rfc.RfcStructureUtil.FromRfcStructure(Byte src, Type t, Encoding encoding, PropertyInfo propinfos, RfcStructInfo structInfo)
at SAP.Connector.Rfc.RfcStructureUtil.FillListWithITab(SAPConnection conn, Object list, Int32 itab, Type t, RfcStructInfo structInfo)
at SAP.Connector.Rfc.RfcClient.RfcInvoke(SAPClient proxy, String method, Object methodParamsIn)
at SAP.Connector.SAPClient.SAPInvoke(String method, Object methodParamsIn)
at SAPProxies.ManufactOrderAPS.CreateFromTemplate(String CHANGE_IF_EXISTS, String COMMIT_CONTROL, String EVENT_CONTROL, String EXT_NUMBER_ASSIGNMENT, String LOGICAL_SYSTEM, String ORDER_TYPE, String PLANNING_MODE_USAGE, String PLANNING_VERSION, BAPI10503ORDSTRATPROFSET STRATEGY_PROFILE, BAPI10503ACTCHARINTable& CHARACTERISTICS_VAL_ACT, BAPI10503IONODECHARINTable& CHARACTERISTICS_VAL_IO, BAPIPAREXTable& EXTENSION_IN, BAPI10503ORDMAPRETOTable& MAPPING_DATA, BAPI10503TMPLPPMCAPREQINTable& ORDER_CAPREQS, BAPI10503TMPLPPMCOMPINTable& ORDER_COMPONENTS, BAPI10503TMPLPPMHEADINTable& ORDER_HEAD, BAPI10503TMPLPPMMODEINTable& ORDER_MODES, BAPI10503TMPLPPMCOPYINTable& ORDER_STRUCTURE, BAPIRET2Table& RETURN)
The link below is exactly the same type of error but from a different vendor. The conclusion is that there is some invalid code in the 3rd party provider (i.e. SAP .NET Connector).
I have looked at the Proxies and my gut feeling is that this might be related to the FFC_NUM which is stored as a string but represents a number. Or it might be the RFC_BCD type causing a problem.
Message was edited by: Chris Brookes
this is really an interesting issue:
1. Why is .NET runtime using 2.0 framework?
2. The 2.0 in NCo.
About 1.: I'm 100% sure that in case the 2.0 is installed, for some reason the program runs on the 2.0 runtime. The app.config doesn't have an effect on .NET loader's choice which runtime it uses - and the basic libraries are AFAIK anyway loaded according the runtime version. The runtime used is determinded by a flag in the EXE-header that is set by the compiler. The 1.x should enter here something different than the 2.x compiler. There are also some registry settings that control the behavior.
In the Don Box .NET book I found an environement variable that overrided any automatic runtime joice. Unforturnately I don't have the book available in the moment, so I can't tell you the exact syntax.
2. The problem of NCo runtime with conversion, but with the behavior change of the function Type.GetProperties(): The order of the returned PropertyInfos is changed in 2.0 which could lead to the fact that the NCo runtime tries to store a String value to a Double property.
A workarround is simply calling <mySAPStructure>.GetProperties() from you code on all affected SAP structures before doing anything with NCo.
To be honest I do not fully understand your suggestion however it is starting to sound like the only solution would be in SAP .NET Connector itself. We actually pass in our table data using Interop and an ADODB recordset. However the code that converts this to the DataTable format required by .NET Connector is the following
While Not rs.EOF
Row = io_InputDataTable.NewRow
For Each Fld In rs.Fields
Row.Item(Fld.Name) = Fld.Value
l_ColumnType = io_InputDataTable.Columns(Fld.Name).DataType
If (Fld.Value Is Nothing) Or (Convert.IsDBNull(Fld.Value)) Then
Row.Item(Fld.Name) = Convert.DBNull
Select Case Type.GetTypeCode(l_ColumnType)
Row.Item(Fld.Name) = Convert.ChangeType(Fld.Value, TypeCode.String)
Row.Item(Fld.Name) = Convert.ChangeType(Fld.Value, TypeCode.Int32)
In other words, we convert the data to the exact form needed by the underlying DataTable before we pass it in to the .NET Connector.
However this information comes direct from the SAPProxies DLL.
Is it possible that the proxies generated by the .NET Connector are providing the wrong type to the underlying RFC call? I have read somewhere that type checking in 2.0 is stricter than 1.1 (e.g. you cannot implicitly convert a string to a decimal in 2.0 even if it is numeric). My theory is that the SAP .NET Connector itself might be doing something incorrect with certain data types.
You can do the workarround on your own.
Look at the proxies that .NET connector created for you: It contains a bunch of classes that inherit from SAPStructure. It could e.g. be called BRFCKNA1. There are also some classes generated that inherit from SAPTable, e.g. BRFCKNATable. These type are used inderectly by you using FromADODataTable().
Before using these types, just make sure that you call "GetProperties" for the underlying structure type.
E.g. at the beginning of your program call:
It sounds strange, but believe me: It will solvhe the problem.
> We actually pass in our table data using Interop and
> an ADODB recordset. However the code that converts
BTW: This can also explain that you unintentially run the CLR 2.0 as runtime as soon as it is installed. If you simply use COM-Interop (.NET classes registered via Regasm), the first COM object will determine the used CLR. If e.g. in HKCR\CLSID\<clsid>\InprocServer32\RuntimeVersion is set to "v2.0.30728" for the clsid of the very first COM class used, the CLR will be 2.0 and stay so as long as the process runs. You may have a chance to fix this by creating an entry at HKLM\SOFTWARE\Microsoft\.NETFramework\policy\AppPatch\v2.0.50727.00000 , but I don't know details.
I have checked the RunTime in the registry key indicated and the version and it is v1.1.4322 so I do not think this is the problem.
I am not clear about the GetProperties() advice. I did try something related to this and it looked like it actually worked. However the test was not repeatable. There seems to be a random element in any case as sometimes it fails on ManufacOrderAPS.CreateFromTemplate and sometimes this works but it fails on PPDSServiceAPS.ChangePeggingMultiple. It has never failed on ManufacOrderAPS.SaveMultiple2. I would appreciate some more advice/background on this.
For various reasons, the program calls everything indirectly by its string name using System.Reflection. The very first thing we execute is
Assembly assemProxies = Assembly.GetAssembly(typeof(SAPProxies.BAPI10001KEYTable));
Is simply a random type from the assembly in order to get to the assembly in question. From then on we extract methods and parameters by string name only.
I have tried adding the following loop after getting the assembly
for( int i = 0; i < arrTypes.Length; i++ )
Is this what is being suggested or have I misunderstood.
> I have checked the RunTime in the registry key
> indicated and the version and it is v1.1.4322 so I do
> not think this is the problem.
You would need to check this for <b>ANY</b> .NET based COM server that your application might use, including classes from MS!
If you want to be sure that really CLR 2.x was loaded into you process, use ProcessExplorer from Sysinternals to see which DLLs and other files it has loaded.
> I have tried adding the following loop after getting
> the assembly
> for( int i = 0; i <
> for( int i = 0; i < arrTypes.Length; i++ )
> Is this what is being suggested or have I
If arrTypes contains all types exported from your proxy, it should work, but it is actually too much. The "GetProperties" is only necessary for types that inherit from SAPStructure. But it should work if you execute this loop before anything else in your code.
I've got the same error in Bapi_Acc_Document_Post. The solution:
-We have stopped to use a method we constructed using System.Reflection. This method gets the values of members of an 'origin' class and sets these values to the related members of a 'destination' class (members with the same name in both classes), the destination class was a SAPStructure in this case. Doing this manually (without using Reflection) solved my problem.
Please, don't ask why it solved my problem, because i don't know.
Have you tried going to 3.5?
I am successfully using the .net connector... creating the proxy using vs2003...
I then simply reference the dll in my .net 3.5 projects.. (vs2008)
I have not had any issues with type conversion, etc.. and.. being that the .net side is an ecommerce application, has many prices, and other datatypes, I have never received an error.
Sorry Jeffrey Malschick
I have not solved the same issue recompiling the proxy generated code using Visual Studio 2003 instead of Visual Studio 2010.
You will find the right solution at http://scn.sap.com/thread/1223041
Looks like SAP Note 0001413789 fixes the issue.