function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
venturec3venturec3 

How can I dynamically cast a QueryResult to an sObject and view the values returned in the QueryResult without having to specify an actual sobject such as Account or Contact?

How come I can't dynamically cast a QueryResult to an sObject and view the values without have to cast the result to a difinitive sObject? I've been able to view returned values from a query within Microsoft Access, loop through the queryresult and then insert record values into the appropriate tables without having to specifiy whether it is an Account or Contact, or Lead, etc.

Instead of having to do something like:
sObject s = new Account();
Account a = Account(s).

Why can't I just loop through the sObject records and retrieve the values?

I'm working on an integration piece and the sObject type has to be dynamic. I cannot cast it to a specific sobject every single time I need to retrieve records.

try
                    {
                        QueryResult qResult = sfProd.query(strSelectStatement);
                        sObject[] s = qResult.records;
                       
                        Boolean done = false;

                        if (qResult.size > 0)
                        {
                            while (!done)
                            {
                                // foreach statement cannot operate on variables of type QueryResult because QueryResult does not contain a public definition for GetEnumerator
                                //foreach (QueryResult q in qResult)
                                //{
                                //}
                               
                                for (Int32 j = 0; j < qResult.records.Length; j++)
                                {
                                    MessageBox.Show(s[j].GetType().ToString());
                                    MessageBox.Show(s[j].GetType().Name);
                                    //MessageBox.Show(s[j].GetType().GetFields("Name").ToString());
                                    MessageBox.Show(s[j].Id.ToString());
                                }

                                if (qResult.done)
                                {
                                    done = true;
                                }
                                else
                                {
                                    qResult = sfProd.queryMore(qResult.queryLocator);
                                }
                               
                            }
                        }
                    }
                    catch (SoapException e)
                    {
                        MessageBox.Show(e.Message);
                    }

SuperfellSuperfell
You should use the partner WSDL instead of the enterprise WSDL, it has a more dynamic programming model which is much more suited to generic tasks like this.
venturec3venturec3
I checked the Partner WSDL and it did not provide access to all of the sObjects in our org. However, I did see that the attributes in the Partner WSDL file were slightly different for the Dynamic sObject portion and copied the values from there to the Enterprise WSDL

           <!-- Dynamic sObject -->
            <complexType name="sObject">
                <sequence>
                    <element name="type"               type="xsd:string"/>
                    <element name="fieldsToNull"       type="xsd:string" nillable="true" minOccurs="0" maxOccurs="unbounded"/>
                    <element name="Id"                 type="tns:ID" nillable="true" />
                    <any namespace="##targetNamespace" minOccurs="0" maxOccurs="unbounded" processContents="lax"/>
                </sequence>
            </complexType>

Now in my C# class, I could use the System.XML.XmlElement / Any as shown in the partner examples:

Here is the result:
In the class I added:

using System.Xml;
.
.
.
                    try
                    {
                        QueryResult qResult = sfProd.query(strSelectStatement);
                        sObject[] s = qResult.records;
                       
                        Boolean done = false;

                        if (qResult.size > 0)
                        {
                            while (!done)
                            {
                                for (Int32 j = 0; j < qResult.records.Length; j++)
                                {

                                    foreach (XmlElement e in s[j].Any)
                                    {
                                        MessageBox.Show(e.LocalName);
                                        MessageBox.Show(e.InnerText);
                                    }

                                }

                                if (qResult.done)
                                {
                                    done = true;
                                }
                                else
                                {
                                    qResult = sfProd.queryMore(qResult.queryLocator);
                                }
                            }
                        }
                    }
                    catch (SoapException e)
                    {
                        MessageBox.Show(e.Message);
                    }

Thank you Superfell for the suggestion of using the Partner WSDL file. This helped get me past the wall I was against.
Aarti IyerAarti Iyer
I tried the above approach but am getting this error. What am I doing wrong? I am in the same predicament i.e. I do not know ahead of time what the object type is going to be. Any help is appreciated. I am using .NET 4.0.

Error 107 foreach statement cannot operate on variables of type 'method group' because 'method group' does not contain a public definition for 'GetEnumerator' 
Error 108 Foreach cannot operate on a 'method group'. Did you intend to invoke the 'method group'? 


Here is my code.
String SOQL = ParseSOQL(p.SOQL);
queryResult = SfdcBinding.query(SOQL);
sObject[] s1 = queryResult.records;
if (queryResult.size > 0)
{
      for (int i = 0; i < queryResult.records.Length; i++)
     {
               //sObject con = queryResult.records[i];
              foreach (XmlElement e in s1[i].Any)
              {
                    string sName = e.LocalName;
                    string sText = e.InnerText;
               }
       }
}

 
Jason Smith 23Jason Smith 23

you can use the dynamic data type in 4.0 framework and then use reflection on the object to figure it out:

 

        ProdSforce.sObject[] records = qr.records;
        for (int i = 0; i < records.Length; i++)
        {
            dynamic queriedObject = records[i];
            Type accType = queriedObject.GetType();
        }      
Vinit Kulkarni 6Vinit Kulkarni 6

I was able to fetch body of the docx file in InnerText of Any object saved in Salesforce documents using partner wsdl from C#.
Now the problem I am facing is, I am not able to parse and save the InnerText as docx file and save it locally. :(
Can someone guide me how to decode the InnerText content and save it as docx file from C#.

            string SOQL = "SELECT Id, Name, Body FROM Document where Id = '" + id + "'";

            QueryResult queryResult = SfdcBinding.query(SOQL);
            
           // below line not working. Tried other encodings also but no success.
            byte[] filebytes = Encoding.ASCII.GetBytes(queryResult.records[0].Any[2].InnerText);  

            File.WriteAllBytes(localfilepath, filebytes);