I have a custom object. There are combination of fields like month_c,Project_c,contact_c and role_c which determine the record as unique.
I can write a trigger on before insert to check if there are any records with the same combination already existing. The question i wanted to ask was
how can i make the insertion stop. once i find there is already an record then it should just not insert the record. it doesnt need to throw / show an error.
Thanks
Prady
Although others have answered this with better solutions (generally non-code solutions are more flexible for the end users of the system), the answer to stop a particular record from being inserted is to add an error to a field on that record.
For instance, if I was inserting accounts I might have something like this:
for(Account sAcct : trigger.new)
{
if(sAcct.Name == 'DeniedAccount')
{
sAcct.Name.addError('This is a denied account.');
}
}
Another alternative is to create a class extending Exception, and then throw a new instance of that exception class, this will prevent all of the records passed to the trigger from being processed as opposed to specific records.
A few days ago I found an incredibly useful and simple solution (in a ForceTree.com article) that prevented me from having to write a trigger. It allows you to combine fields to check for uniqueness using a workflow rule and a custom field.
Here's a walk-through:
http://www.forcetree.com/2010/07/unique-field-combination-in-salesforce.html
I have a similar situation in Salesforce. It is handled by creating a field that contains a value composed of all the values needed to guarantee uniqueness (in your case, month_c,Project_c,contact_c and role_c ). You then select the "Unique" checkbox for that field. Duplicates will now end up in the trash.
In my case, this new field is filled in (and pushed into Salesforce) by an external program. In your case, you'll need to fill in the value in your trigger. I think this is more efficient than doing SOQL queries in a trigger, but I have not done any checking to confirm this.
Related
Setup
I have a Master-Detail relationship, and on the master, I sum up a field from the Detail object.
Question:
I need to allow the user to check a box on the master object which will add the sum by 1 or decrement by 1. How do I do this?
Here's what I've tried:
In an after update trigger on the master increment/decrement within the trigger. Of course I get an error:
expected exception, contact your administrator: NonCashCompAfterUpdate: execution of
AfterUpdate caused by:
Created a new field, and used the existing field as a helper. Basically, I've hidden the old RFS while still using it. This works, but I wanted to see if there was a better way.
Before I went any further I wanted to check in for ideas.
Thanks!
There is no way to directly alter values on a roll-up summary field in salesforce, except by altering the underlying detail records. The second proposal, as I understand it, would involve three fields, the roll-up summary, the checkbox, and the displayed summary (which would be a formula field). The displayed summary field would look something like this:
Rollup_Summary_Field__c + IF(Checkbox_Field__c, 1, -1)
The read-only nature of a roll-up summary field is preserved in Apex as well, so you would not be able to alter it through a trigger. Presumably, that is the nature of the error that you got, though the excerpt that you have attached omits the actual error.
I have came across very interesting problem which I think it's on Salesforce's end but I would like to hear your thoughts on this.
If any of you used Formula Fields to bring a record type name from a particular record to another record might have seen this.
For an example I have record type called "Record Type X" on opportunity and "Record Type Y" on the account record.
When I use $RecordType.Name in the formula fields (RTNameAcc_c & RTNameOpp_c) on both records, the name of their record type is coming across correctly. However, the problem occurs when I reference the account record type on the opportunity record. If I create new formula field on the opportunity called AccountRTName__c and put the following formula Account.RTNameAcc__c instead of the related Account record type name (Record Type Y), I'm getting the opportunity record type name (Record Type X) instead.
I am aware that the formula in AccountRTName__c becomes Account.$RecordType.Name which is fine and should get the Account record type.
So my question is: Is it correct that when you use $RecordType in any context and formula field, the record type is referencing to parent object of the field? And if so, does anyone have a different solution to this problem (without using custom settings)?
Correct, the $ context variables are resolved in a non-intuitive way in this use case. It's been a long time since I've dealt with this issue, but the solution I last saw was either a workflow field update on the source record or a trigger. Try the field update path, if that doesn't work, you'll probably need a trigger. I don't think this issue has a purely formula-based solution, but as I said it's been a while since I've dealt with it.
I'm currently creating my first real life project in Pervasive. The task is to map a certain XML structure containing orders (as in shops and products) to 3 tables I created myself. These tables rest inside a MS-SQL-Server instance.
All of the tables have a unique key called "id", an automatically incremented column. I've dropped this column from all mappings so that Pervasive will not try to fill it itself.
For certain calculations, for a split key in one of the tables and for references to the created records in other tables, I will need the id that the database has just created. For that, I have googled the answer. I can use "select ##identity;" as a statement, and this returns the id that has most recently been created for the current connection. This means that in Pervasive, I will have to execute this statement using the already existing target connection object.
But how to do that? I am quite sure that I will need a JDImport or DJExport object, but how to get one associated with the current connection that Pervasive inserts the records by?
Or is there any other way to handle this auto increment when I need to reference the id in other tables?
Not sure how things work in Pervasive, but you may run into issues with ##identity,. Scope_identity() would probably be safer but may still not work in Pervasive.
Hopefully your tables have a natural key in addition to the generated id, in which case you can select your id based on the natural key. This will avoid any issues you may have with disparate sessions and scope.
If there is anyone looking this post up and wonders about the answer, it's "You can't". Pervasive does not allow access to their very own connection object, the one they use to query the database. Without access to it, you cannot guaranteed fetch the right id. The solution for us was this: We used a stored procedure which we called in the Before-Transformation event that created the header record and returned the id and an optional error message as a table. We executed it and it returns the id we then save and use throughout our mapping.
I am getting the following error in an MS Access ADP when trying to add a record on a form linked to a MS SQL Server 2000 table:
Run-time error '31004':
The value of an (AutoNumber) field
cannot be retrived prior to being
saved.
Please save the record that contains
the (AutoNumber) field prior to
performing this action.
note: retrieved is actually spelled wrong in the error.
Does anyone know what this means?
I've done a web search and was only able to find the answer at a certain site that only experts have access to.
First of all, if you are going to look at experts-exchange - do it in FireFox, you'll see the unblocked answers at the bottom of the page.
Second, do you have a subform on that form that's using the autonumber/key field on the master form? Do you require the data that's on that subform to be saved (i.e., having its own key) before the main form is saved. You could be into a deadlock of A and B requiring each other to be saved first.
Other than that, you must somehow be accessing that autonumber field whenyou are saving it. The best I can suggest is to step through the code line by line.
Are you trying to assign the value of an Identity field to a variable or something else before you have saved the record?
For whatever reason, your app is trying to read the value of the identity field before the record has been saved, which is what generates that identity field. In other words, no value exists for the Autonumber field until the row is saved.
I think we'd need to see more code or know more about the steps that lead up to this error to resolve it in more detail.
You should have add some lines of code to show us how you're managing your data and what you are doing exactly. But I am suspecting an issue related to a recordset update. can you identify when the autonumber value is created? Is it available in a control on a form? Can you add a control to display this value to check how it is generated when adding a new record? Is the underlying recordset properly updated? Can you add something like me.recordset.update on some form events: I would try the OnCurrent one ...
I asked about setting up an in-memory dataset with TClientDataset, and was told I had to use the "Create Data Set" command in the form designer. That works just fine until I try to create a master-detail database relation. If I have a field def of type ftDataSet, then running the Create Data Set command (or calling the method at runtime) gives an "Invalid Field Type" error. I did a few searches and found that other people have had this problem before, but nobody ever seems to come up with an answer. Does anyone know how to fix this?
Instead of putting your detail in a ftDataSet column, just use a unique integer or GUID for the key reference, and place the detail data in a different TClientDataSet and have that key. Like you would in a normal database. Each TClientDataSet representing a different table.
If you create a field of type ftDataSet, you need to define the dataset, else the type is not valid.
You can define the dataset, by:
select the field.
select the ChildDefs property and click the [...] button.
add the fields.
Now you can create the dataset. Unless one of the children is of type ftDataSet in which case you have to recursively repeat the process.
A nasty problem that cost me a lot of time already. Finally I found a workaround, described here (Thanks you guys!):
http://www.delphigroups.info/3/6/171869.html
Summary: The culprit are the field definitions of the master client dataset, i.e., the one that contains the ftDataset fields. As soon as the field definitions of the master client dataset are not empty, the command CreateDataSet fails with the above described error message ("Invalid Field Type").
Workaround:
Create master-detail tables as instructed, but make sure the field definitions are empty when doing CreateDataset:
a) Designtime: Before you do "master dataset | RightClick | Create DataSet" in the design form, you have to click on the master dataset, go to object inspector, click on FieldDefs, and delete all the fields in the FieldDefs window. (The very first time you built the master dataset there are none in there anyway, but later there are.) Only then do Create Dataset. (I tried this myself with Delphi 2007; it works.)
b) Runtime: Call [Name of Masterdataset].FieldDefs.Clear before you do [Name of Masterdataset].CreateDataSet. (I did not try this out myself, but it is credibly described in the above named link.)
If this was too complicated, please look in the above mentioned link.