Shawn Weisfeld

I find when I talk to myself nobody listens. - Shawn Weisfeld
posts - 352, comments - 144, trackbacks - 34

My Links

News

The views expressed in this blog are mine and mine alone, not that of my employer, Microsoft, or anyone else’s. No warrantee is given for the quality of any material on this site.

Archives

Post Categories

Using XML\A and C# to Query SAP BW

Need to query SAP BW from your .NET application? This is a trivial task with XML\A and C#. XML\A is a specification that allows multidimentional datasources to be queried by applications. It is how Reporting Services talks to SAP BW (http://technet.microsoft.com/en-us/library/bb508810(SQL.90).aspx).

Step 1: Find out the path to your SAP BW XML\A service, Mine looks something like this "http://<Server>:<Port>/sap/bw/xml/soap/xmla"

Step 2: Open a .NET project and create a web reference to that service, I called mine MsXmlAnalysis

Step 3: Modify the WebService Proxy Class, When .NET generates the proxy class it declares the Execute Mehtod with two arguments the ExecuteCommand and a PropertiesType. The PropertiesType is a base class for the DiscoverProperties object, but has no properties. To fix this we actually want to pass a DiscoverProperties object to the Execute Method. While this compiles fine the XML serializer has a problem serializing the request. To fix this add "[XmlElement(typeof(DiscoverProperties))]" before the PropertiesType argument in the Execute Methods Signature. It should look like this "public System.Xml.XmlElement Execute([System.Xml.Serialization.XmlElementAttribute(IsNullable=true)] ExecuteCommand Command,  [XmlElement(typeof(DiscoverProperties))]PropertiesType Properties) {"

Step 4: Execute the MDX Query:
using (MsXmlAnalysis.MsXmlAnalysis ws = new MsXmlAnalysis.MsXmlAnalysis())
{
 //the _userId and _password are your login credentials to the SAP Server
 NetworkCredential nc = new NetworkCredential(_userId, _password);
 //the url is the path you found in Step 1
 ws.Credentials = nc.GetCredential(new Uri(url), "Basic");
 ws.Url = url;

 MsXmlAnalysis.ExecuteCommand cmd = new MsXmlAnalysis.ExecuteCommand();
 cmd.Statement = "MDX QUERY HERE";

 MsXmlAnalysis.DiscoverProperties properties = new MsXmlAnalysis.DiscoverProperties();
 properties.PropertyList = new MsXmlAnalysis.DiscoverPropertiesPropertyList();
 properties.PropertyList.LocalIdentifier = "1033";
 properties.PropertyList.DataSourceInfo = "default";
 properties.PropertyList.Content = "SchemaData";
 properties.PropertyList.Format = "Tabular";

 XmlElement elem =  ws.Execute(cmd, properties);
 //Do something with the element here
}

You can also query metadata out of the SAP BW using the XML\A

Here is a list of different requests you can do: DISCOVER_DATASOURCES, DISCOVER_PROPERTIES, MDSCHEMA_CUBES, MDSCHEMA_CUBES, MDSCHEMA_DIMENSIONS, MDSCHEMA_HIERARCHIES, SAP_VARIABLES, MDSCHEMA_MEASURES, MDSCHEMA_PROPERTIES. If you want to limit your search to a specific cube specify a catalog and cube specify those values also (some of the queries require catalog and cube to be specified).

using (MsXmlAnalysis.MsXmlAnalysis ws = new MsXmlAnalysis.MsXmlAnalysis())
{
 NetworkCredential nc = new NetworkCredential(_userId, _password);
 ws.Credentials = nc.GetCredential(new Uri(url), "Basic");
 ws.Url = url;

 MsXmlAnalysis.DiscoverProperties properties = new MsXmlAnalysis.DiscoverProperties();
 properties.PropertyList = new MsXmlAnalysis.DiscoverPropertiesPropertyList();
 properties.PropertyList.LocalIdentifier = "1033";
 properties.PropertyList.DataSourceInfo = "default";
 properties.PropertyList.Content = "SchemaData";
 properties.PropertyList.Format = "Tabular";

 MsXmlAnalysis.DiscoverRestrictions restrictions = new MsXmlAnalysis.DiscoverRestrictions();
 restrictions.RestrictionList = new MsXmlAnalysis.DiscoverRestrictionsRestrictionList();

 if (catalog != null && cube != null
     && catalog.Length > 0 && cube.Length > 0)
 {
     restrictions.RestrictionList.CATALOG_NAME = catalog;
     restrictions.RestrictionList.CUBE_NAME = cube;
 }

 XmlElement elem = ws.Discover(request, restrictions, properties);
 //Do something with the element here
}

Print | posted on Thursday, June 14, 2007 3:04 PM | Filed Under [ .NET ASP.NET C# SAP ]

Feedback

Gravatar

# re: Using XML\A and C# to Query SAP BW

Shawn,
Great and helpful article. I have one question on the Xml that comes back from SAP(like below). The problem is that the descriptive column names are in the Schema section and the column names in the actual xml are in a "C00000#" format.

How do I would convert this data into a DataSet or DataTable object that has the columns named with the names in the schema?

<root xmlns="urn:schemas-microsoft-com:xml-analysis:rowset" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="www.w3.org/2001/XMLSchema-instance">
<xsd:schema xmlns="urn:schemas-microsoft-com:xml-analysis:rowset" targetNamespace="urn:schemas-microsoft-com:xml-analysis:rowset" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:sql="urn:schemas-microsoft-com:xml-sql" elementFormDefault="qualified">
<xsd:element name="root">
<xsd:complexType>
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element name="row" type="row" />
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="uuid">
<xsd:restriction base="xsd:string">
<xsd:pattern value="[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}" />
</xsd:restriction>
</xsd:simpleType>
<xsd:complexType name="row">
<xsd:sequence minOccurs="0" maxOccurs="unbounded">
<xsd:element name="C000000" type="xsd:string" sql:field="[ZFISQUART].[LEVEL01].[MEMBER_CAPTION]" />
<xsd:element name="C000001" type="xsd:string" sql:field="[ZDBBUS].[LEVEL01].[MEMBER_CAPTION]" />
<xsd:element name="C000002" type="xsd:string" sql:field="[Measures].[ZDBOPINC]" />
<xsd:element name="C000003" type="xsd:string" sql:field="[Measures].[ZDBORONA]" />
<xsd:element name="C000004" type="xsd:string" sql:field="[Measures].[ZDBORONAR]" />
<xsd:element name="C000005" type="xsd:string" sql:field="[Measures].[ZDBNETASS]" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
<row><C000000>FY04Q1</C000000><C000001>Sales</C000001><C000002>10,000.00 USD</C000002><C000003>0.000</C000003><C000004>0.000</C000004><C000005>100,000.00 USD</C000005></row>
<row><C000000>FY04Q1</C000000><C000001>Marketing</C000001><C000002>1,200.00 USD</C000002><C000003>0.000</C000003><C000004>0.000</C000004><C000005>125,000.00 USD</C000005></row>
</root>

8/6/2008 3:23 PM | Brian S
Gravatar

# re: Using XML\A and C# to Query SAP BW

johni2i The think you need to edit is the "Proxy Class" this is what .NET created when you added the web reference. If you press the "Show All Files" button in the Solution Explorer in VS.net you should see it hiding there. It will be the file with the big message on top that says dont edit it :)
10/27/2008 4:37 PM | sweisfeld
Gravatar

# re: Using XML\A and C# to Query SAP BW

schwinbp The dataset object has a method that will allow you to suck the xml into it. (msdn.microsoft.com/.../...ata.dataset.readxml.aspx)
10/27/2008 4:40 PM | sweisfeld

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 4 and 2 and type the answer here:

Powered by: