64
You need getSobject() to traverse relationship "up" in a dynamic way.
sObject acc = [SELECT Owner.Profile.Name FROM Account LIMIT 1];
String profileName = (String) acc.getSobject('Owner').getSobject('Profile').get('Name');
System.debug(profileName);
Check all dynamic get* methods in the Sobject instance methods docs.
53
in APIv26 there's a new method, Id.getSObjectType() which returns a sObject token you can use to find it's type. Sample code:
String objectAPIName = someId.getSObjectType().getDescribe().getName();
This new style uses much less heap space and script statementsCPU time in addition to being much simpler and is highly recommended.
Don't do this anymore, but ...
43
You can resolve this in your test class by using System.runAs.
System.runAs ( new User(Id = UserInfo.getUserId()) ) {
...your setup-object DML...
}
If you need to do this in a non test scenario @future, Batch Apex, apex:actionFunction or something as simple as user button flow, it can be used to separate the transactions. The Salesforce documentation ...
answered Jun 27 '13 at 10:12
Andrew Fawcett
38.1k44 gold badges9090 silver badges124124 bronze badges
37
I know this approach is strange because you are still working with a List<SObject>, but when you assign it you can make it more specific (e.g. List<Account>) by using Type.forName and Type.newInstance methods.
public static void dynamicUpsert(List<SObject> records)
{
Schema.SObjectType sObjectType = records.getSObjectType();
if (...
answered Aug 17 '15 at 17:11
35
You've got the general idea from your answer. Dynamic Apex and Dynamic SOQL are the best way to reflect on SObject's and as you've discovered you can determine the type easily. I would ensure however your method takes a list of SObject so it can implement bulkfication.
public void createTask(List<SObject> records)
You can use the List method ...
answered Oct 1 '13 at 16:02
Andrew Fawcett
38.1k44 gold badges9090 silver badges124124 bronze badges
28
There is no way to Select * with SOQL. You can however work-around this limitation by using dynamic SOQL and describe methods to get all of the fields on the object. This is described in detail in this post by Cory Cowgill:
Building Dynamic SOQL - Select All Query
25
New feature coming in the next release:
Foo__c f = Foo__c.sobjecttype.newSObject(
recordTypeId, // can be null
true); // loadDefaultValues
24
I use SObject as a key when I want to use a composite key. For example, say I want to find duplicates based on first name, last name, and email. I might loop through a list of contacts, and create a contact that matches the keys I'm using:
Incoming.put(new Contact(FirstName= record.FirstName, LastName= record.LastName, Email= record.Email), record);
Then, ...
22
Get All Parent objects.
for(Schema.SobjectField strFld: Account.SobjectType.getDescribe().fields.getMap().Values())
{
if(strFld.getDescribe().getType() == Schema.DisplayType.REFERENCE)
{
system.debug('==parent object='+strFld.getDescribe().getReferenceTo());
}
}
Get All Child objects.
Schema.DescribeSObjectResult R = Account....
20
Here is the way:
// I have Account name in String
String objectStr = 'Account';
// Convert to schema.sObjectType
Schema.SObjectType convertType = Schema.getGlobalDescribe().get(objectStr);
// Create an instance of that type
Sobject genericObject = convertType.newSObject();
// or if I know it is Account !! why making Sobject ?
Account acc = (Account)...
19
If you already know the ID of the SObject you want to update then you're right, there's no need to waste a query just to get an SObject instance to work with.
Your sample code is very close to working, but you need to remember that the constructors for SObjects are special and accept named arguments, something unique to them in all of apex. Your sample code ...
18
Sadly I have to report the answer to your question is no. For me this is the final peace of Dynamic Apex to complete the ability to build truly 100% dynamic Apex libraries and solutions.
I've searched for workarounds and can find none, the addError methods on SObject use a highly specialised way to reference the field which is to hard code the field ...
answered Jun 12 '13 at 22:15
Andrew Fawcett
38.1k44 gold badges9090 silver badges124124 bronze badges
17
The question is not very clear, but you could do something with the JSON.deserializeUntyped method as following:
testobject__c tObj = [SELECT boolfield__c,currencyfield__c,datetimefield__c,formulafield__c,Id,Name,numberfield__c,textfield__c,url_field__c FROM testobject__c limit 1];
Map<String, Object> m = (Map<String, Object>) JSON....
answered Feb 21 '13 at 12:41
Samuel De Rycke
9,05488 gold badges3737 silver badges6666 bronze badges
17
Once you have the sObjectType you should be able to construct the sObject instance using the sObjectType.newSObject(ID Id) method. You can get the sObjectType from the Id using the Id.getSObjectType() method;
Map<Id, String> idsToUpdate = new Map<Id, String>();
// Put the Id's and associated name values in the map
List<SObject> ...
answered Oct 9 '13 at 19:31
Daniel Ballinger
87.6k1818 gold badges173173 silver badges458458 bronze badges
17
I'm not sure you could do exactly that, but what you could do is use the Id instance class to achieve what you need, for example:
Schema.SObjectType sobjectType = myId.getSObjectType();
String sobjectName = sobjectType.getDescribe().getName();
SObject record = Database.query('Select Id, Name From ' + sobjectName + ' Where Id = :myId');
See ID class ...
17
I created some helper classes for this. You can find them here.
There are 3 classes: xt, xs and xr. They contain also some other tools I couldn't separate for this answer, but the method you need is xs.query() in xs.cls. To get all straight into your Org, just use the "Deploy to Salesforce" link.
The usage is very simple. Just go somewhere to Execute ...
17
As a regular user, the only way would be to either attempt to create a record from a related object then look at the URL to get the prefix or view an existing record and look at the url.
If the user has access to the dev console you can debug this line of code:
system.debug(logginglevel.error,OBJECTAPINAME.sobjecttype.getDescribe().getKeyPrefix());
...
16
Yes, deepClone will only pull in fields you have in memory. In this case, you do indeed have to query for them. You should question why you need every field, but if you want to maintain a configurable option, I recommend you use a Field Set. This will allow you some flexibility in which fields to copy, without forcing you to copy every single field.
public ...
answered Sep 30 '16 at 21:30
15
You could vote for this Provide an additional addError method on SObject that accepts a field name idea, but as it has got nowhere in the last 5 years there is no reason to expect any progress in the next 5 years.
15
Using complex objects as Map keys can have unexpected consequences.
In your example, the insert causes the Id of the key Account to be updated so the hashCode and equals methods of the Account produce different results after that. But the Map was setup with the original hashCode and equals results. Effectively you have modified the key and that has broken ...
14
UPDATED: Following comment request see below for related fields
There is no method on the SObject class that can be used to determine if a field has been queried. I would add this to the 'hasError' method request as well btw!
In the meantime I can see two options...
Catching SObjectExceptions
You can catch the exception that is generated from ...
answered Jan 16 '14 at 6:45
Andrew Fawcett
38.1k44 gold badges9090 silver badges124124 bronze badges
13
Update
We can now query those 01I object ids and 00N field ids directly without Tooling API or callouts.
List<EntityParticle> entities = [
SELECT DurableId
FROM EntityParticle
WHERE EntityDefinition.QualifiedApiName = 'MyCustom__c'
];
This will return:
DurableId
01I7F000001fbTC.LastViewedDate
01I7F000001fbTC.LastReferencedDate
...
13
I suggest that rather than relying on some utility class, you become familiar with the platform's APIs so you can compose the appropriate solution each time you want to query all the fields, particularly if your queries are simple and only involve one object. Whoever gets to maintain the code in the future will thank you for keeping things simple and direct ...
13
Mechanics
You need to use the get and put methods. Each method supports both String and SObjectField as the parameter type:
// terse
myObject.put('UniqueId__c', myObject.get('ExternalId__c'));
// verbose
SObjectField fieldToGet = MyObject__c.ExternalId__c;
SObjectField fieldToPut = MyObject__c.UniqueId__c;
Object value = myObject.get(fieldToGet);
myObject....
answered May 5 '17 at 15:26
13
I know that when you serialize an SObject it has some extra information on it that you might not expect:
Contact c = new Contact();
system.debug(json.serialize(c));
Result:
{"attributes":{"type":"Contact"}}
I think the error message is simply telling you that you need to include this in your JSON that you send back to the controller so that it knows what ...
11
Without sample code, it's hard to be certain, but I think you are saying you have something like this:
//You have a custom object, Widget__c, with a lookup to account
Widget__c widget = [select id, name, Account__c from Widget where id = :someId];
List<Account> accounts = new List<Account>();
accounts.add(widget.account__c); // <-- error ...
11
This works fine for me. Ran a couple tests and all of the below work.
VF Page
<apex:page controller="GenericTest">
{!test['name']}
{!test1.obj['name']}
<apex:repeat value="{!testList}" var="test2">
{!test2.obj['name']}
</apex:repeat>
<apex:pageBlock>
<apex:pageBlockTable value="{!testList}" ...
answered Jun 6 '14 at 0:11
Ralph Callaway
22.3k1212 gold badges8484 silver badges164164 bronze badges
11
An SObject represents a specific table in the database that you can discretely query. The API Name is what you reference as ending in __c. Standard SObjects have names like Account or Opportunity, whereas Custom SObjects and Custom Settings have names like MyObject__c or MySetting__c. Custom Settings are special objects you can get without a query.
You can ...
answered Jul 17 '16 at 0:02
11
I suggest building and serializing nested maps for this:
Map<String, Object> m = new Map<String, Object>();
for (options__C opt:options) {
m.put(opt.Name__c, new Map<String, Boolean>{
'isActive' => opt.isActive__c,
'isRequired' => opt.isRequired__c
});
}
return JSON.serialize(m);
10
You can use apex describe to get the record type details of any object. This information will be correct for the running user.
Schema.DescribeSObjectResult dsr = Account.SObjectType.getDescribe();
Schema.RecordTypeInfo defaultRecordType;
for(Schema.RecordTypeInfo rti : dsr.getRecordTypeInfos()) {
if(rti.isDefaultRecordTypeMapping()) {
...
answered Oct 15 '12 at 6:21
Daniel Blackhall
7,26488 gold badges4343 silver badges6666 bronze badges
Only top voted, non community-wiki answers of a minimum length are eligible
Related Tags
sobject × 447apex × 197
soql × 42
visualforce × 30
trigger × 25
describesobject × 24
rest-api × 22
custom-object × 21
list × 21
map × 20
fields × 18
soap-api × 16
lightning-aura-components × 14
unit-test × 14
query × 14
json × 14
sobjectfield × 14
custom-field × 13
sobjecttype × 13
standard-objects × 12
dynamic-apex × 12
schema × 11
salesforce-id × 10
metadata-api × 8
dynamic-soql × 8