+ Start a Discussion
neilatklcgneilatklcg 

Simple question

I know this has to be documented somewhere, but I don't see it in the Web Services api documentation, samples or anywhere in this forum. But I SWEAR I looked.

I want to do the most generic query on the sforce types: returning all the complete objects. I want to do the equivalent of select * from Contacts (or possibly returning complete objects: select from Contacts). All I see are queries that require fieldlists, and I don't want to have to list them all since I need the complete object.

There must be a way to do this. Can someone please point me in the correct direction?

Thanks in advance.
SuperfellSuperfell
call describeSObject first to get the list of fields, and build the select field list from that.
neilatklcgneilatklcg
I saw this, and it didn't seem like what I was looking for. One of the great advantages of working with Web Services is (obviously) the ability to pass around objects. I want the object. As I read the documentation, your suggestion returns me a set of tuples corresponding to columns, right?
SuperfellSuperfell
I'm not sure what you're getting at. Web Services pass around XML, nothing more, nothing less. Your tooling may or may not map that to an object, but that's a tooling thing, not a web services thing.

To access data in sforce (either via query or retrieve) you need to specify the fields you're interested in, this provides a number of things including efficiency (if all you want is account name, do you really want us to return 250 other fields on all 2 million of your accounts, that's a lot of wasted bandwidth and processing for both you and us), it also allows for evolution of the data without affecting existing integrations.
neilatklcgneilatklcg
True, Web Services pass XML, but typically that XML is the serialized representation of an object. Code on each side of the interface is responsible for serializing and deserializing the object. Sforce even provides the client side objects that should be mapped (in the soap/enterprise/sobject package). Those are the objects I want.

It is also true that it can be more efficient to allow the client to specify which properties are to be retrieved, but only if the number of columns is small. If the client wants (let's say) ten or more columns or the whole object, this methodology makes life way more complex. That's why most APIs I have seen allow the client to retrieve data both ways. You apparently don't. Fine.

But just to make sure I understand this: If I want to retrieve an object of type sforce.soap.enterprise.sobject.Account, I have to instantiate it, query every data column, and then manually populate all the properties individually? And then do the same thing for every Account in my dataset?
SuperfellSuperfell
If you're using the enterprise API, then the queryResults contains an array of SObject's, each SObject is of the type you queried against, you simply downcast it to the correct type (assuming your in .NET or Java or a similar environment), so no, no extra instaniate, or copying to do.

If you're in the partner API, then you'll get an array of MessageElements (or similar) and you'll need to either work directly with that array, or copy the data to some other structure. Unless you're in an environment that can dynamically create types at runtime (like the python toolkit, or apache's XML Beans), this can't be mapped to a strongly type object, because its definition isn't known until runtime (and you know which org you're connecting to).

If you take a look at the .NET or Java quickstarts, it should clarify a lot of this for you.
neilatklcgneilatklcg
Awesome... now we are making progress, but this takes me back to my original question. I don't see in any of the documentation (including the quickstarts) how to retrieve the complete object. All of the examples I see involve fieldLists. What is, for example, the SOQL query to retrieve a complete SObject.Acount for id=10? Or all SObject.Accounts?
SuperfellSuperfell
You always have to pass a field list. One of the reasons for this is on the enterprise API, you should only ask for fields that exist on your client object, there could be additional fields created after you generated the enterprise WSDL and if you also query that field then either (a) that fields value gets silently dropped (.NET) or (b) the toolkit complains that it received an element it wasn't expected (Axis).
You can either manually work out the select list out, or use reflection to build it. (Again this all assume your in a .NET or Java environment) Which toolkit are you using?
neilatklcgneilatklcg
Interesting. I am using Java/Axis.
SassbertoSassberto
I hope people are still on this thread - this is a really important thread for people trying to create a generic system on top of the partner API and I think a lot of people are experiencing the same issues here. Obviously you can use the ADO.NET provider and make your life a lot easier than I did :-)

The basic issue the poster is making is that Sforce should return objects, but Sforce instead typically returns strings and arrays of strings.

This is the solution I have arrived to: Fudge an object(s) in a DataSet

- when the app runs for the first time, generate the entire SFDC schema by calling
DescribeGlobalResult, iterating over each type name, pulling the fields and creating a DataTable for each SFDC class using the fieldlists from SFDC. Add each dt to an instance dataset. Serialize the instance Dataset.

- Subsequent runs, deserialize the Dataset and use as your schema. You can force the schema to be re-populated manually.

You now have a 'clean dataset' to use to create inserts, you can also generate populated datasets in a QueryResult to replace your blank ones.

All you do to assign values to your 'object' is pass in key/value pairs to the appropriate datatable. This design should allow for you to model any sForce object from any Datatable as input. Read up on sObject.Any - this allows you to create any sObject from a simple XML doc.

It is a lot of work to do though - you need to validate incoming fields against the schema. It seems to me that typing is not an issue as long as EVERYTHING is a string . And you need to know the fields - Intellisense won't pick them up :-)

Once this was done, it's easy to construct the sObjects:

[Test]
public void TestInherited()
{
//load SFDC schema to dataset
this.InitSchema();

//this.SetVaule just an accessor to dataset rows
this.SetValue("FirstName","Jimbo","Lead");
this.SetValue("LastName","Jones","Lead");
this.SetValue("Email","jimbojones@zavvuvoz.com","Lead");

//construct an XML doc,assign it to a new sObject.Any, pass it
this.Create("Lead");
}

Matt
SassbertoSassberto
I hope people are still on this thread - this is a really important thread for people trying to create a generic system on top of the partner API and I think a lot of people are experiencing the same issues here. Obviously you can use the ADO.NET provider and make your life a lot easier than I did :-)

The basic issue the poster is making is that Sforce should return objects, but Sforce instead typically returns strings and arrays of strings.

This is the solution I have arrived to: Fudge an object(s) in a DataSet

- when the app runs for the first time, generate the entire SFDC schema by calling
DescribeGlobalResult, iterating over each type name, pulling the fields and creating a DataTable for each SFDC class using the fieldlists from SFDC. Add each dt to an instance dataset. Serialize the instance Dataset.

- Subsequent runs, deserialize the Dataset and use as your schema. You can force the schema to be re-populated manually.

You now have a 'clean dataset' to use to create inserts, you can also generate populated datasets in a QueryResult to replace your blank ones.

All you do to assign values to your 'object' is pass in key/value pairs to the appropriate datatable. This design should allow for you to model any sForce object from any Datatable as input. Read up on sObject.Any - this allows you to create any sObject from a simple XML doc.

It is a lot of work to do though - you need to validate incoming fields against the schema. It seems to me that typing is not an issue as long as EVERYTHING is a string . And you need to know the fields - Intellisense won't pick them up :-)

Once this was done, it's easy to construct the sObjects:

[Test]
public void TestInherited()
{
//load SFDC schema to dataset
this.InitSchema();

//this.SetVaule just an accessor to dataset rows
this.SetValue("FirstName","Jimbo","Lead");
this.SetValue("LastName","Jones","Lead");
this.SetValue("Email","jimbojones@zavvuvoz.com","Lead");

//construct an XML doc,assign it to a new sObject.Any, pass it
this.Create("Lead");
}

Matt