Newbie q.: Binding a TextBox to an entity

Posts   
 
    
9ppel
User
Posts: 17
Joined: 26-Feb-2007
# Posted on: 26-Feb-2007 23:28:17   

Newbie-questions

Been trying to read the helpfiles and looked at tutorials, but can't seem to find out of this:

Using LLBLGen Pro v. 2.0.0.0 final Runtime library version 2.0.7.219 .NET 2.0, SQL Server 2005

I've generated a SelfServicing entity from a table of my database, opened it in VS05, built it and added a WindowsProject (cleverly named 'Gui') to the solution. I've referenced the first project from the latter, and also the ORMSupportClasses.NET20. In the entity-project I have referenced ORMSupportClasses.NET20 and DQE.SqlServer.NET20.

Problem 1: In the tutorial-video CompilingTheCode there is used some handy LLBLGEN codesnippets to add using-statements to the code. I don't have those snippets in my VS05. How do I install them?

Problem 2: I add an object data source to my solution, and drag three fields into the form (two fields that together is the PK, and an extra field). I then get a EntityBindingSource and an EntityBindingNavigator in my form as well. But when I compile, the navigator doesn't have any buttons enabled, except the "+"-button. I can click it, but I am never able to save the new record, as the save-button is disabled. Do I have to initialize the entity in some way, or what am I doing wrong here?

bclubb
User
Posts: 934
Joined: 12-Feb-2004
# Posted on: 27-Feb-2007 03:55:19   

Take a look in the LLBLGen/VSNet2005Snippets folder. It has a readme.txt that explains how to get them setup.

Are you using an object data source or the LLBLGenDatasource?

9ppel
User
Posts: 17
Joined: 26-Feb-2007
# Posted on: 27-Feb-2007 07:05:47   

bclubb wrote:

Take a look in the LLBLGen/VSNet2005Snippets folder. It has a readme.txt that explains how to get them setup.

OK, great, thank you.

Are you using an object data source or the LLBLGenDatasource?

I'm using an object data source. Something tells me that this is wrong simple_smile How can I use the LLBLGenDatasource?

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 27-Feb-2007 07:27:32   

LLBLGenProDatasource is used in Web apps.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 27-Feb-2007 10:24:56   

You've to fetch the data first into the entity collection that's created on the form. As the collection is empty, you can just add a new one, but not browse existing. So when the form is loaded (in the form load event) you have to fetch the data into the collection on the form, for example by calling collection.GetMulti(null)

Frans Bouma | Lead developer LLBLGen Pro
9ppel
User
Posts: 17
Joined: 26-Feb-2007
# Posted on: 27-Feb-2007 12:16:52   

Otis wrote:

You've to fetch the data first into the entity collection that's created on the form. As the collection is empty, you can just add a new one, but not browse existing. So when the form is loaded (in the form load event) you have to fetch the data into the collection on the form, for example by calling collection.GetMulti(null)

Which collection? There's no code in the Form_Load, the EntityBindingSources' DataSource seems to be a classname (<namespace>.EntityClasses.CustomerEntity), so I don't know which object to manipulate, and I didn't think that an Entity-object was a collection?

Aurelien avatar
Aurelien
Support Team
Posts: 162
Joined: 28-Jun-2006
# Posted on: 27-Feb-2007 18:08:15   

Hi,

Do you use ObjectDataSource with an object witch has method for Select, insert and/or delete ?

9ppel
User
Posts: 17
Joined: 26-Feb-2007
# Posted on: 27-Feb-2007 19:12:50   

Aurelien wrote:

Hi,

Do you use ObjectDataSource with an object witch has method for Select, insert and/or delete ?

I made a new object datasource from <namespace>.CustomerEntity (the entity generated by LLBLGen), then I choose the menu item Data/Show Data Sources. From the Data Sources-window I drag and drop the fields into the form. Then VS05 automatically adds also a CustomerEntityBindingSource and a CustomerEntityBindingNavigator.

If any of those objects have methods for Select etc I don't know. I thought this should work right out of the box, just as if I use Data Connections fram the Server Explorer etc., but I'm obviously missing something, a small detail I guess.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 27-Feb-2007 20:58:25   

I think (but am not sure, as I don't have the exact code / form you created in front of me) that what the winforms designer created is a definition (BindingList<T>) bound to the bindingsource but not an actual instance.

So what you should do is in the form load event create a CustomerEntity instance, fetch its data and set the bindingsource.DataSource property to that instance.

Frans Bouma | Lead developer LLBLGen Pro
9ppel
User
Posts: 17
Joined: 26-Feb-2007
# Posted on: 27-Feb-2007 21:26:14   

Otis wrote:

I think (but am not sure, as I don't have the exact code / form you created in front of me) that what the winforms designer created is a definition (BindingList<T>) bound to the bindingsource but not an actual instance.

So what you should do is in the form load event create a CustomerEntity instance, fetch its data and set the bindingsource.DataSource property to that instance.

This takes me one step further:

    private void MainForm_Load(object sender, EventArgs e)
    {
        CustomerEntity customer = new CustomerEntity();         
        CustomerEntityBindingSource.DataSource = customer;
    }

I can now enter values in the textBoxes, and then press the "+"-button. Then a "record" is added, and the back-arrow is enabled. I can then navigate between records, but I can never persist them, as the save-button is never enabled.

Also, the customer-records from the database never shows up.

I'm not sure how to "fetch it's data", as you say it. As I have understood it, an entity (e.g. customerentity) has "room" for just one record at a time. (and a collection has room for many entities). So I would expect the record in the customer-object to change when I press the navigation-buttons of the navigator. Am I totally wrong in thinking this?

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 28-Feb-2007 07:24:23   

Are you using some sort of control like FormView or Details View, or did you manually add the navigation buttons?

If yes, then I think you should use an EntityCollection instead of an Entity, fetch it first, then bind it to a binding Source.

Now the DetailsView for example should display the first record in the table, and you can navigate back and forth between the records.

Ref: LLBLGen Pro manual: "Using the generated code -> Adapter/SelfServicing -> Databinding with Windows Forms and ASP.NET 1.x"

9ppel
User
Posts: 17
Joined: 26-Feb-2007
# Posted on: 28-Feb-2007 08:14:13   

Walaa wrote:

Are you using some sort of control like FormView or Details View, or did you manually add the navigation buttons?

If yes, then I think you should use an EntityCollection instead of an Entity, fetch it first, then bind it to a binding Source.

Now the DetailsView for example should display the first record in the table, and you can navigate back and forth between the records.

Ref: LLBLGen Pro manual: "Using the generated code -> Adapter/SelfServicing -> Databinding with Windows Forms and ASP.NET 1.x"

FormView and DetailsView, that's ASP.NET-things I think, isn't it (haven't been programming that much .NET)? I'm trying to make a simple Form. And VS05 added both the navigator and the bindingsource all by itself, when I dragged the fields from the data source into the form.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 28-Feb-2007 09:44:52   

I think it was/is a bit confusing what form type you're working with as you mentioned 'Object datasource' which is an asp.net control.

Frans Bouma | Lead developer LLBLGen Pro
9ppel
User
Posts: 17
Joined: 26-Feb-2007
# Posted on: 28-Feb-2007 10:01:59   

Otis wrote:

I think it was/is a bit confusing what form type you're working with as you mentioned 'Object datasource' which is an asp.net control.

OK, sorry about that.

What I ment was that I used "Add New Datasource" under the menu Data in VS05 and then chose "Object", not "Database" or "Web Service" as data source. I then choose Data/Show Data Sources, which gives me the window with "Data Sources". From here I drag and drop some fields from the CustomerEntity into the Windows Form.

I just don't understand why I can't get this working, it should really be "The hello world" of database applications smile

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 28-Feb-2007 11:05:55   

9ppel wrote:

Otis wrote:

I think it was/is a bit confusing what form type you're working with as you mentioned 'Object datasource' which is an asp.net control.

OK, sorry about that.

What I ment was that I used "Add New Datasource" under the menu Data in VS05 and then chose "Object", not "Database" or "Web Service" as data source. I then choose Data/Show Data Sources, which gives me the window with "Data Sources". From here I drag and drop some fields from the CustomerEntity into the Windows Form.

I just don't understand why I can't get this working, it should really be "The hello world" of database applications smile

haha simple_smile ok, I now understand what's going on simple_smile

Ok, here's the deal. When you follow these steps you're describing, the winforms designer will setup your controls, but not with instances of the type(s) you dragged onto the form (e.g. CustomerEntity). It will setup the controls with TYPE definitions of the type. When you go into the form1.designer.cs sourcecode, you'll see in the initializecomponent routine something like: this.customerEntityBindingSource.DataSource = typeof(Northwind.EntityClasses.CustomerEntity);

(I created a winforms app, dragged a customer entity from the datasources window in detail mode onto the form, and got the navigator and bindingsource.)

This means, the whole form is setup with a type, instead of a real instance.

Now, what you should do is this. In your form code, create a CustomerCollection instance and if you want to edit existing data, load it first, like I've done in the code below:


namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            CustomerCollection customers = new CustomerCollection();
            // get all customers
            customers.GetMulti(null);
            // bind collection to bindingsource to show them in the form.
            customerEntityBindingSource.DataSource = customers;
        }
    }
}

When you now fire up the form, you'll see existing data and you can add new entities, edit existing ones etc.

Saving the data isn't enabled. This is natural, as the navigator obviously doesn't know how to save data. So you click the disk button in the navigator in design view of the form, and go to properties, there you'll see it's disabled. Make Enabled = true, and double click the disk button. An event handler is created. In THERE you'll save the data: ((CustomerCollection)customerEntityBindingSource.DataSource).SaveMulti();

What you can also do, is bind an event handler to customers.ListChanged event, and in there make the save button enabled/disabled.

Good luck simple_smile

Frans Bouma | Lead developer LLBLGen Pro
9ppel
User
Posts: 17
Joined: 26-Feb-2007
# Posted on: 28-Feb-2007 11:27:05   

I love the smell of success in the....eh....."morning" smile

Otis wrote:

haha simple_smile ok, I now understand what's going on simple_smile

Indeed, you did simple_smile

Ok, here's the deal. When you follow these steps you're describing, the winforms designer will setup your controls, but not with instances of the type(s) you dragged onto the form (e.g. CustomerEntity). It will setup the controls with TYPE definitions of the type. When you go into the form1.designer.cs sourcecode, you'll see in the initializecomponent routine something like: this.customerEntityBindingSource.DataSource = typeof(Northwind.EntityClasses.CustomerEntity);

Correct! The code's in there, just as you said.

Now, what you should do is this. In your form code, create a CustomerCollection instance and if you want to edit existing data, load it first, like I've done in the code below:


namespace WindowsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            CustomerCollection customers = new CustomerCollection();
            // get all customers
            customers.GetMulti(null);
            // bind collection to bindingsource to show them in the form.
            customerEntityBindingSource.DataSource = customers;
        }
    }
}

I initially got an exception, saying that connection-string was not properly set, but after I copied the App.Config to the Gui-project of the solution it all runs nice. And the records from the database shows up correctly simple_smile

I'm on my way now, I think. Great. Looking forward to be working with this product.

Thanks a bunch for all the help. Next step is to try out the SAVEing part, guess it will be easy now.

9ppel
User
Posts: 17
Joined: 26-Feb-2007
# Posted on: 28-Feb-2007 13:07:34   

Actually, it didn't save the record. I enabled the save-button and entered your code into the click-event. If I try to edit an exisiting record and save it nothings happens. No exceptions or anything, but it doesn't save, either.

If I try to add a new record and click the save-button, I get the exception shown on the attached picture.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 01-Mar-2007 10:30:03   

This is because the entity isn't really added yet at that stage, because the edit hasn't been finalized. If you press ESC you could remove it automatically.

So you have to end edit first. You do this by adding the line: customerEntityBindingSource.EndEdit(); before the save action.

Deletes also require you to be performed by yourself. Removal from the collection doesn't mean the entity gets deleted from the db. This is done this way because it's ambiguistic: sometimes you just want to remove an entity from a collection and not remove it from the db

Frans Bouma | Lead developer LLBLGen Pro
9ppel
User
Posts: 17
Joined: 26-Feb-2007
# Posted on: 01-Mar-2007 12:21:42   

Otis wrote:

This is because the entity isn't really added yet at that stage, because the edit hasn't been finalized. If you press ESC you could remove it automatically.

So you have to end edit first. You do this by adding the line: customerEntityBindingSource.EndEdit(); before the save action.

That worked, OK. When I try to alter the value of the PK (CustomerID) there seems to be some kind of validation that kicks in. Focus can't leave the TextBox, and save doesn't work. Which is of course a good thing. To override this validation-behaviour (e.g. add a messagebox), do I have to use the "TwoClasses"-template?

Deletes also require you to be performed by yourself. Removal from the collection doesn't mean the entity gets deleted from the db. This is done this way because it's ambiguistic: sometimes you just want to remove an entity from a collection and not remove it from the db

OK. Sorry for being such a pain in the b**t here, but I tried to implement the delete-button. Then I guess I need access to the "current customerentity"-object from the collection. I seem to rememer there's an object or property in the form that keeps track of this (a BindingManager or something?), but I'm not able to find it right now. Just for the fun of it I tried this:

    private void bindingNavigatorDeleteItem_Click(object sender, EventArgs e)
    {
        customerEntityBindingSource.EndEdit();
        ((CustomerCollection)customerEntityBindingSource.DataSource)[0].Delete();
    }

but that gave me an unhandled ORMQueryExecutionException. Any tip?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39927
Joined: 17-Aug-2003
# Posted on: 02-Mar-2007 11:23:57   

9ppel wrote:

Otis wrote:

This is because the entity isn't really added yet at that stage, because the edit hasn't been finalized. If you press ESC you could remove it automatically.

So you have to end edit first. You do this by adding the line: customerEntityBindingSource.EndEdit(); before the save action.

That worked, OK. When I try to alter the value of the PK (CustomerID) there seems to be some kind of validation that kicks in. Focus can't leave the TextBox, and save doesn't work. Which is of course a good thing. To override this validation-behaviour (e.g. add a messagebox), do I have to use the "TwoClasses"-template?

The PK field is readonly when the field is part of an existing entity and this validation is build inside the entity code. Though it's not when it's a new entity. This is the reason the PK field property has a setter. VS.NET's designer does only look at the setter and enables the textbox no matter what.

In the logic vs.net adds to the form there's no logic which checks if the property descriptor for the field reports that hte field is readonly or not.

Deletes also require you to be performed by yourself. Removal from the collection doesn't mean the entity gets deleted from the db. This is done this way because it's ambiguistic: sometimes you just want to remove an entity from a collection and not remove it from the db

OK. Sorry for being such a pain in the b**t here, but I tried to implement the delete-button. Then I guess I need access to the "current customerentity"-object from the collection. I seem to rememer there's an object or property in the form that keeps track of this (a BindingManager or something?), but I'm not able to find it right now. Just for the fun of it I tried this:

    private void bindingNavigatorDeleteItem_Click(object sender, EventArgs e)
    {
        customerEntityBindingSource.EndEdit();
        ((CustomerCollection)customerEntityBindingSource.DataSource)[0].Delete();
    }

but that gave me an unhandled ORMQueryExecutionException. Any tip?

Removing a customer which is refered to by entities in the db of course won't work. You need to remove these also.

Cascading deletes aren't done, this is a design decision: cascading deletes aren't always possible, for example if multiple paths lead from one entity to another: in that case sqlserver for example also gives up when you enable cascading deletes in the db. Furthermore, cascading deletes can lead to the wipe out of the complete db, so you've to implement them yourself so you can opt for setting fk fields to NULL instead of removing the entities for example in one situation.

Frans Bouma | Lead developer LLBLGen Pro