Can I programatically add new record
-
Tuesday, January 15, 2013 11:14 PM
I have a question for ya'll:
How do I programatically add a new record to a table that is not in the current screen (from the current screen).
More specifically, let's say I have 3 tables:
- Houses - contains info about a House. There is an associated screen called HousesDetail for adding a new House.
- Counties - contains info about a County. There is an associated screen called CountiesDetail for adding a new County.
- Houses2Counties - contains references (fields) to a House record (entity) and a County record (entity).
I have a data entry screen which has a modal picker to select a county, a button to add a new county, a modal picker to select a house, and a button to add a new House.
In the HousesDetail screen I added a Data Item (Parameter) called Counties_Parameter so that if a user has selected a county from the data entry screen and clicked "New House" I can pass in the selected County. In this scenario, I want to not just create a new House record, but I want to also create a new Houses2Counties record after the new House record is saved.
Here is what I'm thinking for logic in the HousesDetail screen (I'm not sure where to put this logic):
When the Record is Saved {
If (a County was passed in) {
create a new Houses2Counties record;
newRecord.Houses = Houses;
newRecord.Counties = Counties_Parameter;
newRecord.SaveChanges();
};
};
First, I'm not sure if this is the correct way to approach the problem - perhaps there is a more elegant solution.
Secondly, I do not know where to put this code. A relevant question is, do I need to have the new House record saved before adding a record to the Houses2Counties table or can I just pass in the Houses entity in it's current state and expet it to work?
Lastly, I do not know what the actual code should look like for my lines of logic.
Thanks in advance for any help and insight.
-Christopher DeMars
All Replies
-
Tuesday, January 15, 2013 11:30 PM
I forgot to mention that since there is a relationship between the Houses table and the Houses2Counties table, I chose to include a Houses2Counties entity in the Houses screen. I don't know if I can use that somehow. When I expand the Houses2Quantities entity in my screen, It only shows fields for the "Selected Item". I'm not sure how to interpret what the "Selected Item" means in this context.
-Christopher DeMars
-
Tuesday, January 15, 2013 11:47 PM
You can update one table when a record is being saved in another table using a method such as this.
You can also do it from an action triggered by the client side using a method such as the one shown at the end of this article:
Saving Data In The Visual Studio LightSwitch HTML Client (Including Automatic Saves)
This shows you an example of all the CRUD functions:
Creating ASP.NET Web Forms CRUD Pages Using ServerApplicationContext
- Edited by ADefwebserverMVP Wednesday, January 16, 2013 12:21 AM
- Edited by ADefwebserverMVP Wednesday, January 16, 2013 12:23 AM
-
Wednesday, January 16, 2013 4:36 AM
Michael,
Thanks for the links. I looked through them and I could not find exactly what I'm looking for.
Since the County is passed in as a parameter to the screen, I'm guessing I need to do my coding on the Client Side. I looked at your post regarding Saving Data in the HTML Client and while you do propose a potential solution, I can't help but think that I can do what I'm trying to accomplish without using Ajax and Custom Server pages.
I think I can just include the new Houses2Counties record as part of the current screens' changes and do one save at the end that includes saves to both the House and the Houses2Counties records. I just need to figure out how to programmatically add a new record.
In the screen created method I tried:
myapp.dataWorkspace.ApplicationData.Houses2Counties.AddNew().then(function (result) { result.House = House; result.County = County_Parameter; });But I get an error saying something about not being able to execute AddNew() because the object is undefined or null.
I was thinking that I may have to do something with the linked Houses2Counties selected item that appears in my screen designer. I know that if I drag that Entity into my screen it creates a list control displaying all the Houses2Counties records. I can create a button and one of the options is to do a Add or Edit New Houses2Counties record, so it looks like there is some built in functionality for creating a new one of these records.
I'm thinking that if LightSwitch has the ability to create a new Houses2Counties record from the Houses screen, that I must be able to tap into that functionality programmatically and do the same thing (create the new record and then populate the fields). The question is, can I do this "in the background" aka. without invoking a new/separate dialog?
If anyone can suggest some specific code, I'd be very grateful.
-Christopher DeMars
-
Thursday, January 17, 2013 9:19 PM
I have a question for Stephen Provine:
I tried to follow the example you provided in your blog post New LightSwitch HTML Client APIs (Stephen Provine) in the Custom Screen Methods section where you show an example of how to call an OData service using a Promise object to import Orders from the sample Northwind OData service.
In the Promise success code you have these lines of code:
for (var i = 0, len = results.length; i < len; i++) { var importedOrder = screen.Orders.addNew(); importedOrder.OrderDate = results[i].OrderDate; }If you take some time and read through the above posts, I'm trying to add a new record, albeit not through an OData call encapsulated in a promise object.
When I try this code modeled after your code:
screen.H2C.addNew().then( function (result) { result.House = Houses; result.County = Counties_Parameter; });When I hit that first line of code I get this error:
For clarity, this screen is a Add/Edit Details screen for the Houses entity, and I added a Data Item called Counties_Parameter which setup as a screen parameter. I also added another Data Item which is a Houses2Counties entity called H2C.
The intellisense is not working in my project, so I cannot tell what kind of object is returned by an addNew() call. It makes sense to me that it would return a Houses2Counties entity, but I wan't sure if it returned a promise object instead. so I also tried:
var objH2C = screen.H2C.addNew(); objH2C.House = Houses; objH2C.County = Counties_Parameter;
I ended up getting the same error as before.
Can you clarify for me why I'm getting this object not defined error and how to overcome this?
Thanks in advance
-Christopher DeMars
-
Thursday, January 17, 2013 10:14 PM
I am sure Stephen will answer when he gets a chance, as you can imagine the entire team is very busy :)
My guess is that in his example Orders is a collection not just a single property, therefore it has an "AddNew()" (I know if intellisense was working you would not have a hard time checking this if it is the case).
So:
Ensure you have a H2C collection on the page (exact spelling please :) this is JavaScript and it is unforgiving)
Also note: The reason I keep pushing the .ashx handler is that even when you get this to work, if you need to implement more complex business logic and then change your data layer, the code will break with no compile time build errors. If you instead use .ashx code it will show any errors on build :)
-
Thursday, January 17, 2013 10:26 PM
Micheal, you make a great point about seperating client-side code from server-side code especially when it comes to error checking.
I just got the followng code to work:
myapp.HousesDetail.created = function (screen) { // Write code here. if (screen.Counties_Parameter != null) { if (screen.Counties_Parameter.County_Name != null) { var objH2C = myapp.dataWorkspace.ApplicationData.Houses2CountiesSet.addNew(); objH2C.Counties = screen.Counties_Parameter; objH2C.Houses = screen.Houses; }; }; };It still seems kind of odd to me that the AddNew() does not return a promise object. Since I'm fairly certain that this method goes to the server, I feel like I should wrap this in my own promise object. What do you guys think? I'm still trying to understand what is and is not wrapped in promise objects by LightSwitch and why.
Anyway, I the code runs without producing an error, but now I get an error when I Save Changes on the screen that says "Save operation failed - Data in the Houses2Counties record is invalid".
Since there are only 3 fields in the record (id, House, and County), and I'm passing in a valid Counties object, so the error must be with the Houses object on the current screen. I'm thinking that since this code gets executed in the screen creation method that might have something to do with it?
I'll try putting this in a button execute method and see what happens.
-Christopher DeMars
- Marked As Answer by ChristopherDeMars Thursday, January 17, 2013 10:26 PM
- Unmarked As Answer by ChristopherDeMars Thursday, January 17, 2013 10:44 PM
- Edited by ChristopherDeMars Thursday, January 17, 2013 10:57 PM
- Edited by ChristopherDeMars Thursday, January 17, 2013 10:57 PM
-
Tuesday, January 22, 2013 8:56 PM
Hi Christopher,
Sorry for the delayed reply. I read your original scenario and where you have landed is basically how I would have solved the problem. I should clarify that the AddNew() method is local only and all it does is create a new instance of an entity in the "added" state which (perhaps confusingly) actually means it is *pending* addition to the database. So AddNew() doesn't return a promise because it doesn't do any asynchronous work.
I'm not sure why you are seeing an issue with this code, unless there's something in how you launched the HousesDetail screen. I assume that the screen has two parameters: Houses and Counties_Parameter. If in the designer you modeled the Houses parameter value to be "(New Houses)", then by the time your screen created code is called, screen.Houses should be set to a new instance of the Houses entity. Perhaps you can debug this code and see if screen.Houses is still null? The save failure message indicates that something is missing in the Houses2Counties entity.
Stephen
Visual Studio LightSwitch Team
-
Tuesday, January 22, 2013 9:49 PM
Stephen, thank you for your response. I know you guys are very busy and I don't want to be the cause of any delay of the next release.
As you suspected, there was something missing in the Houses2Counties entity. I had another required field that [I thought] was being set in the Client side create method of the entity. It turns out that I mistyped the field name so the insert failed on the database side and that raised the exception.
As I said, I fixed this using an button with a custom execute method. But I now want to do away with the button and have this all happen in the background. So now I have a new problem - where should I put this code? Ideally, I would put it some method that gets executed right before the screen is saved, but I don't think such a place exists in the HTML client.
Does anyone out here in the community know where I should put this code so it runs automatically behind the scenes?
My last resort (and very unelegant solution) would be to code my own save button and override the existing save button. Michael Zlatkovsky suggest something like this in this post. I know that the LS team is not allowed to comment on what will or will not be in the next release on LS, but since there are many posts asking for a hook into the save method, it would be absolutely wonderful if that made it into the next release. I really don't want to create all my own save buttons when there is a good one already there. I just need it to call my code before finishing the job.
-Christopher DeMars
-
Tuesday, January 22, 2013 9:57 PM
Christopher,
Maybe I'm missing something here - is there a reason it doesn't work in the screen created code? Why do you want to wait to create this entity until right before you actually save to the server?
Stephen
Visual Studio LightSwitch Team
- Marked As Answer by ChristopherDeMars Thursday, January 24, 2013 3:26 AM
-
Thursday, January 24, 2013 3:28 AM
That works of course! I don't know why I didn't think of that...
Not enough sleep I guess. And too deep in the code. It's easy to lose perspective. Typical programmer problem.
Thanks for tip Stephen.
-Christopher DeMars

