Consultor Eletrônico



Kbase P146403: A .NET client is unable to receive a static ProDataSet parameter from an OpenEdge Web Service as a .
Autor   Progress Software Corporation - Progress
Acesso   Público
Publicação   6/11/2010
Status: Unverified

SYMPTOM(s):

A .NET client is unable to receive a static ProDataSet parameter from an OpenEdge Web Service as a .NET Dataset

A .NET client receives a static ProDataSet parameter as a class object instead of an .NET Dataset object

FACT(s) (Environment):

OpenEdge 10.1C
OpenEdge 10.2A
All Supported Operating Systems

CAUSE:

Because .NET has a proprietary method of recognizing and exposing .NET Dataset in WSDL documents, its toolkit cannot translate the WSDL definitions of a ProDataSet directly into an .NET Dataset.

FIX:

To workaround this limitation, a .NET client can walk the object arrays and populate a .NET Dataset with the data. For example, the following snippet of code is from a procedure that passes a static ProDataSet parameter:
/* getDynDs.p */
DEFINE INPUT PARAMETER iCustNum AS INTEGER EXTENT 2.
DEFINE OUTPUT PARAMETER DATASET FOR dsCustOrd.
/* Create dataset based on criteria
** fill dataset and return to caller */
...
When you add a Web Reference to the CustOrdersService Web service in Microsoft Visual Studio, the proxies in the Reference.cs file include this method to invoke the getCustOrders operation:
public string getCustOrders([System.Xml.Serialization.XmlElementAttribute("iCustNum", IsNullable=true)] System.Nullable<int>[] iCustNum, out dsCustOrd dsCustOrd) {
object[] results = this.Invoke("getCustOrders", new object[] {iCustNum});
dsCustOrd = ((dsCustOrd)(results[1]));
return ((string)(results[0]));
}
...

public partial class dsCustOrd {
private dsCustOrdTtCust[] ttCustField;
private dsCustOrdTtOrder[] ttOrderField;
...

public partial class dsCustOrdTtCust {
private System.Nullable<int> custNumField;
private string nameField;
private System.Nullable<decimal> balanceField;
...

public partial class dsCustOrdTtOrder {
private System.Nullable<int> orderNumField;
private System.Nullable<int> custNumField;
private System.Nullable<System.DateTime> orderDateField;
...
You can then create code that invokes the Web service passing in the array for the CustNum range and retrieves the requested data:

private void button2_Click(object sender, EventArgs e)
{
string result = null;
int cntr;
int?[] CustNumRange = new int?[2];

CustOrders.dsCustOrd dsCustOrd;
CustOrders.CustOrdersService mySvc = new CustOrders.CustOrdersService();

try
{
CustNumRange[0] = CustNumLow;
CustNumRange[1] = CustNumHigh;
if (CustNumHigh < CustNumLow) CustNumRange[1] = CustNumRange[0];
result = mySvc.getCustOrders(CustNumRange, out dsCustOrd);
Since you know the schema of the incoming DATASET parameter, the event logic can create a matching .NET DataSet to accept the incoming data, as follows:

// Create a .Net Dataset based on this data
DataSet x = new DataSet("dsCustOrd");
DataTable t1 = x.Tables.Add("ttCust");
DataTable t2 = x.Tables.Add("ttOrder");

t1.Columns.Add("CustNum", typeof(int));
t1.Columns.Add("Name", typeof(string));
t1.Columns.Add("Balance", typeof(System.Decimal));

t1.Columns[0].Unique = true;

t2.Columns.Add("OrderNum", typeof(int));
t2.Columns.Add("CustNum", typeof(int));
t2.Columns.Add("OrderDate", typeof(DateTime));

t2.Columns[0].Unique = true;

DataColumn pCol = t1.Columns[0];
DataColumn cCol = t2.Columns[1];

x.Relations.Add(pCol, cCol);LOCKQUOTE>
Finally, the event logic fills the DataSet with the data from the incoming DATASET parameter and binds the DataSet to a grid, as follows:

//Populate the dataset with data from the SOAP message
GetCustOrders.dsCustOrdTtCust[] ttCust = dsCustOrd.ttCust;
for (cntr = 0; cntr < ttCust.Length; ++cntr)
{
Object[] ooCust = new Object[3];
ooCust[0] = ttCust[cntr].CustNum;
ooCust[1] = ttCust[cntr].Name;
ooCust[2] = ttCust[cntr].Balance;
t1.Rows.Add(ooCust);
}

GetCustOrders.dsCustOrdTtOrder[] ttOrder = dsCustOrd.ttOrder;
for (cntr = 0; cntr < ttOrder.Length; ++cntr)
{
Object[] ooOrd = new Object[3];
ooOrd[0] = ttOrder[cntr].OrderNum;
ooOrd[1] = ttOrder[cntr].CustNum;
ooOrd[2] = ttOrder[cntr].OrderDate;
t2.Rows.Add(ooOrd);
}

//bind Dataset to Grid
myGrid.SetDataBinding(x, "ttCust");
}
catch (Exception ex)
{
MessageBox.Show("getCustOrders Failed: " + ex.Message);
}
}.