How to insert data into 3 custom objects using apex code - salesforce

I have 3 custom objects, Object1, Object2, Object3.
Object2 is the child of Object1.
Object3 is the child of Object2.
So I want to insert multiple records into Object1, Object2, Object3.???

Well, have you actually tried anything?
Simplest action (without using advanced tricks like upsert, external ids etc) is to do it in correct sequence. On successful insert the Id of the record will be returned to the object and you can use it in the lookups to build the relationship.
Account a = new Account(Name = 'test acc');
insert a;
Contact c = new Contact(LastName = 'Test', AccountId = a.Id);
insert c;
AccountContactRole acr = new AccountContactRole(Role = 'President', AccountId = a.Id, ContactId = c.Id);
insert acr;
Alternative would be to do it in whatever order you want and later update the child records with proper references...

Related

How can i create an object in Salesforce that automatically populates any dependent objects?

If i need to creat an Order , I need to first creat an Account and then assign the AccountId to the Order, like the following
Account a = new Account();
a.Name = 'Test';
insert a;
Order order = new Order(
AccountId = a.Id,
Status='Draft',
EffectiveDate = Date.today());
insert order;
Is there a way I can simply create an Order and the dependent objects will be created or is there a way to get what Sobject field the AccountId of the order is related to ?
There is no way for Salesforce to automatically create the dependent sObjects, they will have to be inserted.
Regarding your second question (retrieving the type of sObject from the field name) you can check out this question on Salesforce StackExchange. Below is that code being ran for the AccountId field on the Order object:

Best Way to Merge 3 Columns Together to Make Unique Database Column? Trigger?

I have a table on items what sort of looks like this.
ItemsTbl
id -PK
BrandId- int (FK)
LocationId- int (FK)
Field3 - nvarchar(Max) Json string containing a jsonKey called itemNumber
Now I am building an importer(takes in an excel file) that will mass import a 1000 items at a time. But before I can insert them I have to check if they exist in the database.
If so then update, if not new record.
Ideal world, I would either would like the customer to have a field in their excel file of a unique number(through their pk in the db or something else) and store that in my db. If it matches what we have in our db then update otherwise it is new.
I been told by business that is not possible as they think 90% of the customer base will not be able to figure out how to give us a file with a unique column to use as identifier.
I also can't regenerate the file again with unique numbers as I been told most will be pulling the list fresh each time they decide to import.
So the new idea is to have a new column on the database that will combine BrandId + LocationId + itemNumber then each time a file comes through join those 3 fields from the excel file and do a check.
I am worried of this field becoming out of sync as if they manually go into our system and change any of those 3 fields that field would have to change.
I guess trigger would be the best to stop this but I am not sure if it is possible to have a trigger on a field that contains json.
I am using EF Core, Sql Server 2017.
The reason why I don't try to do something like this
select * from ItemsTbl where BrandId = 1 AND LocationId = 1 And JSON_VALUE('Field3',$.itemNumber) = 12345
is because like I said I am getting 1000 items at a time in, I don't want to do a 1000 separate queries. I rather do 1 query with a in clause then loop through the results of that and update.
I suggest you to use Standard ADO.NET libraries to do this.
Create a Procedure which get Table Valued Parameter as input, and pass your bulk data inside that parameter. After that you can use MERGE function to make both update and insert (UPSERT) operation with one call.
/* Create a table type. */
CREATE TYPE SourceTableType AS TABLE
( BrandId INT
, LocationId INT
, ItemNumber INT
, ...
);
GO
CREATE PROCEDURE dbo.usp_InsertTvp
#Source SourceTableType READONLY
AS
MERGE INTO Table1 AS Target
USING #Source As Source
ON Target.BrandId = Source.BrandId and
Target.LocationId = Source.LocationId and
Target.ItemNumber = Source.ItemNumber
WHEN MATCHED THEN
UPDATE SET OtherParam = Source.OtherParam
WHEN NOT MATCHED BY TARGET THEN
INSERT (BrandId, LocationId, ItemNumber, OtherParam) VALUES (BrandId, LocationId, ItemNumber, OtherParam) ;
On the .Net Side you need use
using (connection)
{
// Create a DataTable with the modified rows.
DataTable myTable = ...;
// Define the INSERT-SELECT statement.
string sqlInsert = "dbo.usp_InsertTvp"
// Configure the command and parameter.
SqlCommand mergeCommand = new SqlCommand(sqlInsert, connection);
mergeCommand.CommandType = CommandType.StoredProcedure;
SqlParameter tvpParam = mergeCommand.Parameters.AddWithValue("#Source", myTable);
tvpParam.SqlDbType = SqlDbType.Structured;
tvpParam.TypeName = "dbo.SourceTableType";
// Execute the command.
insertCommand.ExecuteNonQuery();
}
PS: the code is not tested, It may have syntactical problems.
Merge Syntax
MERGE [ INTO ] <target_table> [ AS ] table_alias
USING <table_source>
ON <merge_search_condition>
WHEN MATCHED [ AND <clause_search_condition> ]
THEN <merge_matched> ] [ ...n ]
[ WHEN NOT MATCHED [ BY TARGET ] [ AND <clause_search_condition> ]
THEN <merge_not_matched> ]
where
merge_matched>::=
{ UPDATE SET <set_clause> | DELETE }
<merge_not_matched>::=
{
INSERT [ ( column_list ) ]
{ VALUES ( values_list )
| DEFAULT VALUES }
}
Reference

Look for records related to another related records within specific criteria

I am trying to created a set of records based on some criteria and i need to figure out the best way to do this.
I want to create a record for every object A and B that has an specific Account object. object A needs to have a status of "DONE", and B a status of "READY" in order to create the record (which will be an Object A with an "Active" status) the fields on the new Object A will copy from some of the Object A and B fields.
This is a process im not triggering from user action but a set of records i need to already dump in the database. I do have a sandbox to start working on and testing then rolling out.
Please let me know the easiest way to do this.
I appreciate the help!
You didn't provide enough info, we don't know how the relations look like. Are A and B related lists under Account? Are they independent or is there some link from one to another?
I'll write what I would do as a script (if needed you could make a batch job out of it or perhaps you'll be more comfortable with Data Loader, reports with cross filters, MS Excel and orgy of VLOOKUPs...)
To identify all "candidate" accounts you can try with this skeleton of a query
SELECT Id, Name
FROM Account
WHERE Id IN (SELECT Account__c FROM A__c WHERE Status__c = 'Done')
AND Id IN (SELECT Account__c FROM B__c WHERE Status__c = 'Ready')
LIMIT 10000
Now, the question about amounts of data. Will it return 10K (which is limit of records you can insert/update/modify in single transaction), if more - you might have to chunk it somehow... Maybe ORDER BY Id, record Id of last processed Account and in next iteration add AND Id > '001....'
Anyway, we got a "candidate", well, maybe he already has an Active A record, we wouldn't want to make a duplicate. And besides we need to pull some fields from B so they'd be copied across. So let's modify the query a bit, to add "subqueries" (think of them as related lists or LEFT INNER JOINs if that helps)
SELECT Id, Name,
(SELECT Id FROM As__r WHERE Status__c = 'Active' LIMIT 1),
(SELECT SomeField__c, SomeOtherField__c FROM Bs__r WHERE Status__c = 'Ready' LIMIT 1)
FROM Account
WHERE Id IN (SELECT Account__c FROM A__c WHERE Status__c = 'Done')
AND Id IN (SELECT Account__c FROM B__c WHERE Status__c = 'Ready')
LIMIT 10000
Nice. So now you need to loop through accounts, see if they contain that at least 1 active record (and if they do - skip). If they don't - create new one.
List<A__c> toInsert = new List<A__c>();
for(Account a : [SELECT...]){
if(a.As__r.isEmpty() && !a.Bs__r.isEmpty()){
toInsert.add(new A__c(
Account__c = a.Id,
Status__c = 'Active',
Foo__c = a.Bs__r[0].SomeField__c,
Bar__c = a.Bs__r[0].SomeOtherField__c + 7
));
}
}
insert toInsert;

How to get the ID from table by passing Name in Entity Framework in Silverlight mvvm?

In my Silverlight with MVVM project, I'm using Entity Framework. I have one table named Customer, with fields CustomerID, Username, age. I have inserted one row programmatically.
Here the CustomerID field is an auto-incremented one. So how can I get the CustomerID value by passing UserName that was inserted?
Need the LINQ Query to get it from Entity Framework..?
Any Help?
The auto-incremented ID should be set in the object, after you call SubmitChanges. That is, for example, newId here should contain the value:
var customer = new Customer { Username = "test", Age = 100 };
dataContext.InsertOnSubmit(customer);
dataContext.SubmitChanges();
var newId = customer.CustomerID;
If you need to get load it subsequently from the database, then use a simple query:
string name = "test";
var customer = dataContext.Customers.Where(customer => customer.Username == test).FirstOrDefault();
if (customer != null)
{
var newId = customer.CustomerID;
}

SQL - Updating multiple records for each record with a matching id in a table

I am bit new on the updating multiple records and i wanted to know the best way to go on about a solution for this, i am writing a stored proc were basically i have two tables,
one that matches a server id to a user id
and another table with record information for each user id with multiple columns with values.
Basically here is how its going to work:
Get all the matching user ids for the specific server id in the tb_UserServerMap table
then foreach userId in the tb_setting table update the columns with the new values
Basic structure of your stored procedure would be:
CREATE PROCEDURE Blah
#Server_ID int /* or whatever data type is appropriate */
as
UPDATE ts
SET
ColumnA = 10 /* New value for column A - maybe passed as a parameter? */
/* More columns here */
FROM
tb_setting ts
inner join
tb_UserServerMap usm
on
ts.user_id = usm.user_id
WHERE
usm.server_id = #Server_ID
I can't fill in more of it without knowing the names of columns to be updated, how those values are obtained, data types, etc.
You don't need a foreach,
Update tblName set firstCol = val1, secondCol = val2 where id in (id1, id2, id3)

Resources