locked
Copy multiple records from Related Entity RRS feed

  • Question

  • So I have really been struggling with something that I thought should be quite easy. I am using Lightswitch 2015 and developing an HTML client.

    I am trying to loop through a returned set of records, and for each record returned I need to do the following 3 things:

    1-Create a new record (newTransactionData)

    2-Set a DataPoint Value to some text (This works easily, setDataPoint1Value(‘Automatically created Record’))

    3-Lookup an associated record from a one-to-many relationship and assign that value to the Category field.

    The problem seems to be when I execute the query for the first time (.execute() is the only way I know, and it is asynchronous), the promise runs after the rest of the items in the For loop because the asynchronous call doesn’t halt to the code to return the results (hence  the benefit of asynchronous code). Since the promise runs after the for loop, the new records have been created and the var newTransactionData only applies to the record that was added last.

    Here is my code:

    myapp.AddEditTransactions.DynamicAddDataPoints_execute = function (screen) {
        myapp.activeDataWorkspace.Tsunami2015SQL.ReferenceDocumentDetailsbyDocNumRev(screen.TransactionLog.DocumentNumber, screen.TransactionLog.DocumentRevision).execute()
            .then(function (result1) {
                for (var i = 0, len = result1.results.length; i < len; i++) {
                    var currentrefdoc = result1.results[i];
    
                    //Create the New Record
                    var newTransactionData = new myapp.TransactionData();
    
                    //Set the Key ID Field in the Many Side of the One-to-Many Relationship
                    newTransactionData.setTransactionNumberLookup(screen.TransactionLog)
    
                    //Assign one of the fields
                    //Problem 1, first click leaves this record blank. Likely because the associated table hasn't loaded yet.
                    currentrefdoc.getDataPointNameLookup().then(function (dpname) {
                        newTransactionData.setDataPointNameLookup(dpname)
                    });
    
                //Assign the generic Text-This works perfectly since it is statically assigned data
                    newTransactionData.setDataPoint1Value('Automatically created Record');
    
                //Lookup the Category from the Lookups Table and set that to the Category Field, using 14 as the place holder for now of the item I am looking up
                myapp.activeDataWorkspace.Tsunami2015SQL.GeneralLookups_SingleOrDefault(14).execute().then(function (result2) {
                    //This is the command that sets the field. By the time this Promise executes, 
                    //newTransactionData only represents the latest added record
                        newTransactionData.setDataPointTypeLookup(result2.results[0])
                    });
    
            };//end of For Loop
        });

    • Edited by Joe DiPari [REVA] Wednesday, April 13, 2016 1:55 PM Title is more fitting.
    Thursday, April 7, 2016 1:25 AM

All replies

  • Hello,

    See the comments near the problem 1 code.  Hope this helps.

    myapp.AddEditTransactions.DynamicAddDataPoints_execute = function (screen) {
        myapp.activeDataWorkspace.Tsunami2015SQL.ReferenceDocumentDetailsbyDocNumRev(screen.TransactionLog.DocumentNumber, screen.TransactionLog.DocumentRevision).execute()
            .then(function (result1) {
                for (var i = 0, len = result1.results.length; i < len; i++) {
                    var currentrefdoc = result1.results[i];
    
                    //Create the New Record
                    var newTransactionData = new myapp.TransactionData();
    
                    //Set the Key ID Field in the Many Side of the One-to-Many Relationship
                    newTransactionData.setTransactionNumberLookup(screen.TransactionLog)
    
                    //Assign one of the fields
                    //Problem 1, first click leaves this record blank. Likely because the associated table hasn't loaded yet.
    
    		// if DataPointNameLookup is a query in the screen designer
    		// try this
    		screen.getDataPointNameLookup().then(function (dpname) {
                        newTransactionData.setDataPointNameLookup(dpname)
                    });
    
    
    		// currentrefdoc may not have a DataPointNameLookup value and therefore
    		// this will return undefined
                    // currentrefdoc.getDataPointNameLookup().then(function (dpname) {
                    //    newTransactionData.setDataPointNameLookup(dpname)
                    //});
    
                //Assign the generic Text-This works perfectly since it is statically assigned data
                    newTransactionData.setDataPoint1Value('Automatically created Record');
    
                //Lookup the Category from the Lookups Table and set that to the Category Field, using 14 as the place holder for now of the item I am looking up
                myapp.activeDataWorkspace.Tsunami2015SQL.GeneralLookups_SingleOrDefault(14).execute().then(function (result2) {
                    //This is the command that sets the field. By the time this Promise executes, 
                    //newTransactionData only represents the latest added record
                        newTransactionData.setDataPointTypeLookup(result2.results[0])
                    });
    
            };//end of For Loop
        });

    Thursday, April 7, 2016 12:40 PM
  • Thank you for taking the time to look at this. I see what you mean about the "Problem 1" area, but this does work on the second click. So perhaps to clarify, it seems to end up with "no data" on the first time through the code, but the second time, i.e. second click of the command button, it does end up with properly retrieved data.

    But the real problem remains near the bottom near the "Lookup the Category" comment. Is there a way to retrieve data from this query that is not asynchronous? Or is there a way to pass the information from each "newTransactionData" into this .execute() promise so that when it retrieves the data it is assigning it to the proper row or entity? Or am I constructing this incorrectly all together? Basically I am trying to copy line items from a similar table (Like a template of rows) but there is one item in this template that needs to be looked up from another entity, the GeneralLookups table.

    Tuesday, April 12, 2016 8:57 PM
  • Interestingly enough, I found a solution to part of the problem and corrected that with the code below. The initial problem I was having was how to "Lookup the Category", and also the problem of the first time through the code, the first copied record was blank. This is listed as Problem 1. I got the idea to use the getEntity methods provided from the promise object.

    But one major problem, still remains and that is this "Waiting for the record to Load" problem. To clarify, when I first open the application and click the "Add Record" button, all of the items that are loaded as promises come up empty. It acts like on the first loop through the code it creates the newTransactionData, calls the promises (getQualifierNameLookup, getUOMLookup, etc) and then loops through the for loop again. On the second or "Last" time through the loop, the items from the promises are retrieved, but by that time the newTransactionData is now referring to the second transaction that was created. So even though the promise runs twice as required, since it is run after the loop is executed it copies the promise data into the last record twice. I can't seem to figure out how to either load the data first, or pass the newTransactionData object into the promises so that is writes the data to the 2 different records.

    One additional note is that after I have run this once, all of the newly created records are populated by the promises perfectly and the code works correctly.

    Maybe there is a much simpler way to just copy the record as a whole, but I would still be missing the "CategoryLookup" because that is a related record.

    Again any help is greatly appreciated.

    myapp.AddEditTransactions.DynamicAddDataPoints_execute = function (screen) {
        myapp.activeDataWorkspace.Tsunami2015SQL.ReferenceDocumentDetailsbyDocNumRev(screen.TransactionLog.DocumentNumber, screen.TransactionLog.DocumentRevision).execute()
            .then(function (result1) {
                for (var i = 0, len = result1.results.length; i < len; i++) {
                    var currentrefdoc = result1.results[i];
    
                    //Create the New Record
                    var newTransactionData = new myapp.TransactionData();
    
                    //Set the Key ID Field in the Many Side of the One-to-Many Relationship
                    newTransactionData.setTransactionNumberLookup(screen.TransactionLog)
    
                    //Assign one of the fields
                    //Problem 1, first click leaves this record blank. Likely because the associated table hasn't loaded yet.
                    currentrefdoc.getDataPointNameLookup().then(function (dpname) {
                        newTransactionData.setDataPointNameLookup(dpname)
                        dpname.getCategoryLookup().then(function (catlookup) {
                            newTransactionData.setDataPointTypeLookup(catlookup)
                        });
                    });
                //Assign the generic Text-This works perfectly since it is statically assigned data
                    newTransactionData.setDataPoint1Value('Automatic Record-' + i);
    
                    currentrefdoc.getUOMLookup().then(function (UOMresult) {
                        newTransactionData.setUOMLookup(UOMresult);
                    });
                    currentrefdoc.getQualifierNameLookup().then(function (QualifierNameResult) {
                        newTransactionData.setQualifierNameLookup(QualifierNameResult);
                    });
                    currentrefdoc.getQualifierUOMLookup().then(function (QualifierUOMResult) {
                        newTransactionData.setQualifierUOMLookup(QualifierUOMResult);
                    });
    
                //Lookup the Category from the Lookups Table and set that to the Category Field, using 14 as the place holder for now of the item I am looking up
                //myapp.activeDataWorkspace.Tsunami2015SQL.GeneralLookups_SingleOrDefault(14).execute().then(function (result2) {
                //    //This is the command that sets the field. By the time this Promise executes, 
                //    //newTransactionData only represents the latest added record
                //        newTransactionData.setDataPointTypeLookup(result2)
                //    });
    
            };//end of For Loop
        });
    };

    Wednesday, April 13, 2016 12:59 AM