Check for existence or catch exception? - salesforce

I want to update a record if the record exists or insert a new one if it doesn't.
What would be the best approach?
Do a Select Count() and if comes back zero then insert, if one then query the record, modify and update,
or should I just try to query the record and catch any system.queryexception?
This is all done in Apex, not from REST or the JS API.

Adding to what's already been said here, you want to use FOR UPDATE in these cases to avoid what superfell is referring to. So,
Account theAccount;
Account[] accounts = [SELECT Id FROM Account WHERE Name = 'TEST' LIMIT 1 FOR UPDATE];
if(accounts.size() == 1)
theAccount = accounts[0];
else
theAccount = new Account();
// Make modifications to theAccount, which is either:
// 1. A record-locked account that was selected OR
// 2. A new account that was just created with new Account()
upsert theAccount;

You should use the upsert call if at all possible, the select then insert/update approach is problematic once you get into the realm of concurrent calls unless you goto the trouble of correctly locking a parent row as part of the select call.

I would try it with a list and isEmpty() function:
List<Account> a = [select id from account where name = 'blaahhhh' Limit 1];
if(a.isEmpty()){
System.debug('#### do insert');
}
else{
System.debug('#### do update');
}

Related

How to automatically copy fields from one Sobject to another

Im trying to create automation to copy Zipcode__c text field in connection sObject to Zip_code__c text field on Prem sObject. I can't use formula references since i need to be able to search copied field. One connection can have many Prems.
trigger updatePremFromConnection on Prem__c (before insert,after insert, after update,before update) {
List<Connection__c> connection = new List<Connection__c>();
for (Prem__c p: [SELECT Connection_id__c,id, Name
FROM Prem__c
WHERE Connection_id__c
NOT IN (SELECT id FROM Connection__c)
AND id IN : Trigger.new ]){
connection.add(new Connection__c(
ZipCode__c = p.Zip_Code__c));
}
if (connection.size() > 0) {
insert connection;
}
}
i need ZIp code field on the prem__c to be auto updated when i edit connection.
There are several issues with this code.
Trigger Object
Your trigger is on the wrong object and is doing exactly the opposite of your stated intent.
i need ZIp code field on the prem__c to be auto updated when i edit connection.
Your trigger on the Prem__c object attempts to copy data to the Connection__c object, while your objective is to copy from Prem__c to Connection__c. You'll definitely need an after update trigger on Connection__c and a before insert trigger on Prem__c; however, if the relationship between the two objects is Lookup or a Master-Detail relationship configured to be reparentable, you'll also need an update trigger on the child object Prem__c to handle situations where the child record is reparented, by updating from the new parent Connection.
Logic
This logic:
for (Prem__c p: [SELECT Connection_id__c,id, Name
FROM Prem__c
WHERE Connection_id__c
NOT IN (SELECT id FROM Connection__c)
AND id IN : Trigger.new ]){
connection.add(new Connection__c(
ZipCode__c = p.Zip_Code__c));
}
really doesn't make sense. It only finds Prem__c records in the trigger set that don't have an associated Connection, makes a new Connection, and then doesn't establish a relationship between the two records. The way that it does this is needlessly inefficient; that NOT IN subquery doesn't need to be there because it can simply by Connection_Id__c = null.
Instead, you probably want your Connection__c trigger to have a query like this:
SELECT ZipCode__c, (SELECT Zip_Code__c FROM Prems__r)
FROM Connection__c
WHERE Id IN :Trigger.new
Then, you can iterate over those Connection__c records with an inner for loop over their associated Prem__c records. Note that above you'll need to use the actual relationship name where I have Prems__r. The logic would look something like this:
for (Connection__c conn : queriedConnections) {
for (Prem__c prem : conn.Prems__r) {
if (prem.Zip_Code__c != conn.ZipCode__c) {
prem.Zip_Code__c = conn.ZipCode__c
premsToUpdate.add(prem);
}
}
}
update premsToUpdate;
Before running the query, you should also gather a Set<Id> of only those records for which the ZipCode__c field has actually changed, i.e., where thisConn.ZipCode__c != Trigger.oldMap.get(thisConn.Id).ZipCode__c. You'd use that Set<Id> in place of Trigger.new in your query, so that you only obtain those records with relevant changes.

Save different data for same user on different Guilds

I set up a stats command as follows
[Command("Stats")]
public async Task StatsOther(SocketUser socketUser = null)
{
if (socketUser == null)
{
socketUser = Context.User;
}
var account = UserAccounts.GetAccount(socketUser);
await Context.Channel.SendMessageAsync($"Hey {socketUser.Mention}, You have {account.Size} long sandwhiches and {account.XP} XP.");
}
And the class UserAccounts searches if there exists in our database a socketUser with the ID property. Now say the same user in on different guild I need to store different data for him but the socketUser.ID will be the same no matter the guild. So when the user tries to use stats command he will see the same data irrespective of the guild he is in right now.
Here is where UserAccounts.GetAccount leads and does its thing,
public static UserAccount GetAccountFromID(ulong ID)
{
var result = from a in accounts
where a.ID == ID
select a;
var FoundAccount = result.FirstOrDefault();
if (FoundAccount == null)
{
FoundAccount = CreateUserAccount(ID);
}
return FoundAccount;
}
Clearly the linq query is checking for IDs and they happen to be the same for a user no matter the guild.
I tried using SocketGuildUser but sadly a socketGuildUser.ID is also independent of the guild. So I am unable to store different data for the same user from different guilds. Using the latest beta available.
How can I achieve this.
You could make use of a Dictionary implemented for each user. Where each user have its own Dictionary<GuildID, Data>.
And on the SQL side (if you are using SQL), you could have a new table, where it has a foreign key constrain on the User ID, and has a Guild ID too.
(The foreign key constrain on userID might not be needed if none of the user's stats is shared between all guilds; Aka you just have a SQL-table which you can do a SELECT stuff FROM tableName WHERE userID = ? AND guildID = ?)

Delete trigger for audit table

I'm working on a web application that executes CRUD operations on some table in a SQL Server database. There will be a logged user in the application executing these operations.
(By the way, I'm using Entity Framework)
Let's say table is
MyTable
MyTableId
SomeColumn
LastModifiedUserId
LastModifiedDate
And I a have an audit table like
MyTableHistory
MyTableHistoryId
MyTableId
SomeColumn
ActionType --ins/upd/del
ActionUserId
ActioDate
And I'm using triggers to insert data on the audit table.
Inserts and updates are easy by consulting the Inserted and Updated tables to find the userid who modified the record.
But what about deletes? Any idea how I might get that info?
There is no such thing as updated table. The two pseudo tables available in DML triggers are inserted and deleted. In the case of insert table deleted is empty, in the case of delete table inserted is empty, in the case of update both tables are populated.
You can create three separate triggers for each action (to distinguish ActionType) or try to combine all in one trigger.
Note: take into account multiple row actions.
Assuming you are using EF to add the information about which user is updating records, the easiest way to capture that information is to have EF perform a 2-step process (UPDATE, DELETE) on the data you wish to delete. You will then need to interpret the two audit rows as part of the same operation.
There is a much more involved solution that "might" work, but I have not tested it. There is more information available below if you wish to explore it.
Blog describing the solution
Stack Overflow post of someone trying it
Another option altogether is to abandon trigger auditing (which is problematic for this very reason) and use Entity Framework instead. Below is an example of how one might accomplish this by overriding the SaveChanges method:
public virtual IEnumerable<System.Data.Entity.Infrastructure.DbEntityEntry> ChangedEntries()
{
return ChangeTracker.Entries().Where(x =>
x.State == EntityState.Added ||
x.State == EntityState.Deleted ||
x.State == EntityState.Modified);
}
public virtual int SaveChanges(string userName)
{
var changes = ChangedEntries();
foreach (var entry in changes)
{
var eventType = entry.State == EntityState.Added ? "A" : entry.State == EntityState.Deleted ? "D" : "U";
var entityType = ObjectContext.GetObjectType(entry.Entity.GetType()).Name;
var oldValues = entry.State == EntityState.Added ? null : JsonConvert.SerializeObject(entry.OriginalValues.ToObject());
var newValues = entry.State == EntityState.Deleted ? null : JsonConvert.SerializeObject(entry.CurrentValues.ToObject());
oldValues = oldValues?.Substring(0, Math.Min(oldValues.Length, 4000));
newValues = newValues?.Substring(0, Math.Min(newValues.Length, 4000));
AuditItems.Add(
new AuditItem
{
EventTime = DateTime.Now,
UserName = userName,
EntityType = entityType,
EventType = eventType,
OldValues = oldValues,
NewValues = newValues
}
);
}
return base.SaveChanges();
}

Salesforce Apex: how to test if trigger was called

I have a trigger in Apex. How do I write a unit test that checks if the trigger was called?
Account account = new Account(Name='Test account');
insert account;
checkIfInsertTriggerCalled(); // how do I implement this?
You should be testing what the trigger does, not just if it was called or not. What does your trigger do?
If you are just trying to see if it inserted then:
Account account = new Account(Name='Test account');
insert account;
List<Account> aList = [SELECT Id, Name FROM Account];
system.assertEquals(1,aList.size());
side note: I would have just left a comment, but I am a few rep short on this site.
edit: Here is the standard page that gets linked to a lot: https://developer.salesforce.com/page/How_to_Write_Good_Unit_Tests

Can't get all rows from a query result using TideSDK API

I'm new to TideSDK so I am doing some tests. I found that the API has some methods to manage and retrieve data stored in a local DB. I created a table named Users with only two fields, id and name (This is the example at http://tidesdk.multipart.net/docs/user-dev/generated/#!/api/Ti.Database.DB), which I have fill with some random numbers and names. This is the function I am using:
function consulta (){
//Open the database first
var db = Ti.Database.openFile(Ti.Filesystem.getFile(
Ti.Filesystem.getApplicationDataDirectory(), 'customdatabase.db'));
var rows = db.execute("SELECT * FROM Users ORDER BY firstName");
while (rows.isValidRow()) {
document.getElementById('resultado').innerHTML = 'The user id is '+rows.fieldByName('id')+', and user name is '+rows.fieldByName('firstName')+'<br>';
rows.next();
}
document.getElementById('filas').innerHTML = rows.rowCount( );
//Release memory once you are done with the resultset and the database
rows.close();
db.close();
}**
My problem is this: Though the result of method rowCounts() is 29 (Meaning, of course, that there are 29 rows in the result), the WHILE block is just out puting one single row instead. Can someone help me to make this work? Shouldn't I use the API for this?
Checkout Sample API Usage for Database module here.
Try this:
while (rows.isValidRow()) {
document.write('The user id is '+rows.fieldByName('id')+', and user name is '+rows.fieldByName('firstName')+'<br >'); rows.next(); } document.getElementById('filas').in nerHTML = rows.rowCount( ); //Release memory once you are done with the resultset and the database rows.close(); db.close(); }
Place the script inside the body

Resources