- Home
- LLBLGen Pro
- LLBLGen Pro Runtime Framework
Populating a combo box with a collection; AW tutorial
Joined: 25-Nov-2007
Hello, I'm having a problem displaying an entity collection in a combo box. I think it is probably my inexperience with Windows Forms, but I can't figure out where to add some code.
I am using LLBLGen Pro 2.5 Final (Feb 4, 2008 ) and working through the tutorial AW (AW.Data, AW.WIN projects) from "Rapid C# Development, Visual Studio 2005, SQL Server 2005 & LLBLGen Pro", by Joseph Chancellor. I have Microsoft SQL Server 2005 (SQL Express) running locally. I'm using .Net 20, Self-servicing, two classes.
I am working on a form (frmOrganization) which displays a tree view of employees (a tree of entity nodes) in an organization when the employee number is put in a combo box and then search button returns the nodes. I was able to complete the form successfully, where you enter the employee number and then see a list of all employees related to that person (managers and people supervised). So the database connection seems fine and the basic form works.
The next step is to change the code by populating the combo box with a list of employee names. This is where I'm not sure what to do. (The form compiles and runs, but I don't get values populated in the combo box.) I modified the EmployeeEntity.cs code generated by LLBLGen, extending the business logic layer, by both importing AW.Data.HelperClasses namespace and adding the custom code from the tutorial. (I've pasted the code added to EmployeeEntity.cs below, as well as the current code for the form, without the "frmOrganization_Load" part.
The next part of the tutorials says to add to the frmOrganization form, "in the form Load event" handler, the following code:
private void frmOrganization_Load(object sender, EventArgs e) { cbEmployee.DataSource = EmpllyeeEntity.GetEmployees(); cbEmployee.DisplayMember = "EmployeeDisplayName"; cbEmployee.ValueMember = EmployeeFieldIndex.EmployeeId.ToString(); }
And I can't figure out where to put this code. Is it done through the GUI? Via properties? Dragged from the toolbox area? I've tried putting it directly in the frmOrganization.cs code in a variety of places. I either get an error about the context not being correct or it compiles and runs, but without any data displayed.
Thanks for any suggestions,
Carol
Here is the added the namespace at the top of EmployeeEntity.cs and added CustomEntityCode:
using AW.Data.HelperClasses;
// __LLBLGENPRO_USER_CODE_REGION_START CustomEntityCode
public static EmployeeCollection GetEmployees()
{
RelationCollection Relations = new RelationCollection();
Relations.Add(EmployeeEntity.Relations.ContactEntityUsingContactId);
ISortExpression LastFirstAlpha =
(ContactFields.LastName | SortOperator.Ascending)
& (ContactFields.FirstName | SortOperator.Ascending);
EmployeeCollection Employees = new EmployeeCollection();
Employees.GetMulti(null,0,LastFirstAlpha,Relations);
return Employees;
}
public String EmployeeDisplayName
{
get
{
return this.Contact.LastName + ", " + this.Contact.FirstName;
}
}
// __LLBLGENPRO_USER_CODE_REGION_END
And here is the frmOrganization,without the Load event part:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using AW.Data; using AW.Data.EntityClasses; using AW.Data.CollectionClasses; using AW.Data.HelperClasses; using SD.LLBLGen.Pro.ORMSupportClasses;
namespace AW.WIN { public partial class frmOrganization : Form { public frmOrganization() { InitializeComponent(); }
private TreeNode FindLowestNode(TreeNode Node)
{
if (Node.Nodes.Count > 0)
return FindLowestNode(Node.Nodes[0]);
else
return Node;
}
private TreeNode MakeNode(EmployeeEntity Employee)
{
TreeNode MyNode = new TreeNode(Employee.Contact.LastName
+ ", " + Employee.Contact.FirstName + " ["
+ Employee.EmployeeId.ToString() + " ]");
MyNode.Tag = Employee.EmployeeId;
return MyNode;
}
private TreeNode GetManagersRecursive(EmployeeEntity Employee)
{
TreeNode EmployeeNode = MakeNode(Employee);
if (Employee.ManagerId != null)
{
TreeNode ManagerNode = GetManagersRecursive(Employee.Manager);
FindLowestNode(ManagerNode).Nodes.Add(EmployeeNode);
return ManagerNode;
}
return EmployeeNode;
}
private TreeNode GetEmployeesRecursive(EmployeeEntity Employee)
{
TreeNode EmployeeNode = MakeNode(Employee);
if (Employee.Manages.Count > 0)
{
foreach (EmployeeEntity Subordinate in Employee.Manages)
{
EmployeeNode.Nodes.Add(GetEmployeesRecursive(Subordinate));
}
}
return EmployeeNode;
}
private void btnSearch_Click(object sender, EventArgs e)
{
tvOrganization.Nodes.Clear();
TreeNode MasterNode;
// Here is where I don't have a value selected, as the list of names doesn't show in // the combo box
EmployeeEntity Employee = new EmployeeEntity(
Convert.ToInt32(cbEmployee.SelectedValue));
TreeNode EmployeeNode = MakeNode(Employee);
if (Employee.Manages.Count > 0)
{
foreach (EmployeeEntity Subordiante in Employee.Manages)
{
EmployeeNode.Nodes.Add(GetEmployeesRecursive(Subordiante));
}
}
if (Employee.ManagerId != null)
{
TreeNode ManagersNode = GetManagersRecursive(Employee.Manager);
FindLowestNode(ManagersNode).Nodes.Add(EmployeeNode);
MasterNode = ManagersNode;
}
else
{
MasterNode = EmployeeNode;
}
MasterNode.ExpandAll();
tvOrganization.Nodes.Add(MasterNode);
}
}
}
Try the following:
private void frmOrganization_Load(object sender, EventArgs e) { cbEmployee.DataSource = EmpllyeeEntity.GetEmployees(); cbEmployee.DisplayMember = "EmployeeDisplayName"; ** cbEmployee.ValueMember = EmployeeFields.EmployeeId.Name;** }
And please debug the GetEmployees method to check if it actually returns a collection of Employees, and you may also examine the generated query and run it against the database to check if it returns a resultset.
Hint: For a better performance, use a prefetchPath in the GetEmployees to fetch the Contact entity along with the Employee entity, rather than using LazyLoading to fetch each Contact alone to display the contact name.
Joined: 25-Nov-2007
Hello, Thanks for the suggestions. I changed the line of code to read: "cbEmployee.ValueMember = EmployeeFields.EmployeeId.Name"
But it didn't seem to make a difference. I still get an empty combobox.
I also looked ahead in the tutorial and added code to use prefetch path. The revised code for the frmOrganization is posted at the end of this message. I also included the frmOrganization_Load method just after the initialization of the form.
I set a couple of breakpoints and also enabled tracing. From this, it appears that the Collection is not getting returned. I'm not sure where to see the generated SQL to test it directly. I am trying to download SQL Profiler, by downloading a trial version of SQL Server 2005. I'm using SQL Express, which does not include the Profiler.
Should I be setting a datasource in the Properties of the design view of the form? When I go to the Properties, I can see the various entities.
Thanks,
Carol
New Code for frmOrganization:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using AW.Data; using AW.Data.EntityClasses; using AW.Data.CollectionClasses; using AW.Data.HelperClasses; using SD.LLBLGen.Pro.ORMSupportClasses;
namespace AW.WIN { public partial class frmOrganization : Form { public frmOrganization() { InitializeComponent(); } private void frmOrganization_Load(object sender, EventArgs e) { cbEmployee.DataSource = EmployeeEntity.GetEmployees(); cbEmployee.DisplayMember = "EmployeeDisplayName"; // cbEmployee.ValueMember = EmployeeFieldIndex.EmployeeId.ToString(); cbEmployee.ValueMember = EmployeeFields.EmployeeId.Name; } private TreeNode FindLowestNode(TreeNode Node) { if (Node.Nodes.Count > 0) return FindLowestNode(Node.Nodes[0]); else return Node; } private TreeNode MakeNode(EmployeeEntity Employee) { TreeNode MyNode = new TreeNode(Employee.Contact.LastName + ", " + Employee.Contact.FirstName + " [" + Employee.EmployeeId.ToString() + " ]"); MyNode.Tag = Employee.EmployeeId; return MyNode; } private TreeNode GetManagersRecursive(EmployeeEntity Employee) { TreeNode EmployeeNode = MakeNode(Employee); if (Employee.ManagerId != null) { TreeNode ManagerNode = GetManagersRecursive(Employee.Manager); FindLowestNode(ManagerNode).Nodes.Add(EmployeeNode); return ManagerNode; } return EmployeeNode; }
private TreeNode GetEmployeesRecursive(EmployeeEntity Employee)
{
TreeNode EmployeeNode = MakeNode(Employee);
if (Employee.Manages.Count > 0)
{
foreach (EmployeeEntity Subordinate in Employee.Manages)
{
EmployeeNode.Nodes.Add(GetEmployeesRecursive(Subordinate));
}
}
return EmployeeNode;
}
private void btnSearch_Click(object sender, EventArgs e)
{
tvOrganization.Nodes.Clear();
TreeNode MasterNode;
IPrefetchPath prefetch = new
PrefetchPath((int)EntityType.EmployeeEntity);
prefetch.Add(EmployeeEntity.PrefetchPathContact);
prefetch.Add(EmployeeEntity.PrefetchPathManages)
.SubPath.Add(EmployeeEntity.PrefetchPathManages)
.SubPath.Add(EmployeeEntity.PrefetchPathManages)
.SubPath.Add(EmployeeEntity.PrefetchPathManages)
.SubPath.Add(EmployeeEntity.PrefetchPathManages);
prefetch[1].SubPath.Add(EmployeeEntity.PrefetchPathContact);
prefetch[1].SubPath[0].SubPath.Add(
EmployeeEntity.PrefetchPathContact);
prefetch[1].SubPath[0].SubPath[0].SubPath.Add(
EmployeeEntity.PrefetchPathContact);
prefetch[1].SubPath[0].SubPath[0].SubPath[0].SubPath.Add(
EmployeeEntity.PrefetchPathContact);
prefetch[1].SubPath[0].SubPath[0].SubPath[0].SubPath[0].SubPath.Add(
EmployeeEntity.PrefetchPathContact);
EmployeeEntity Employee = new EmployeeEntity(
Convert.ToInt32(cbEmployee.SelectedValue), prefetch);
// EmployeeEntity Employee = new EmployeeEntity(
// Int32.Parse(cbEmployee.Text));
TreeNode EmployeeNode = MakeNode(Employee);
if (Employee.Manages.Count > 0)
{
foreach (EmployeeEntity Subordiante in Employee.Manages)
{
EmployeeNode.Nodes.Add(GetEmployeesRecursive(Subordiante));
}
}
if (Employee.ManagerId != null)
{
TreeNode ManagersNode = GetManagersRecursive(Employee.Manager);
FindLowestNode(ManagersNode).Nodes.Add(EmployeeNode);
MasterNode = ManagersNode;
}
else
{
MasterNode = EmployeeNode;
}
MasterNode.ExpandAll();
tvOrganization.Nodes.Add(MasterNode);
}
}
}
I'm not sure where to see the generated SQL to test it directly. I am trying to download SQL Profiler, by downloading a trial version of SQL Server 2005. I'm using SQL Express, which does not include the Profiler.
You don't need the Profiler exactly. LLBLGen offers you to trace the generated SQL. You need to add something like this at your app.config file:
<system.diagnostics>
<switches>
<add name="SqlServerDQE" value="4" />
<add name="ORMPersistenceExecution" value="3" />
</switches>
</system.diagnostics>
And you should see the generated SQL at your VSNet Output window. For more info read LLBLGenPro Help - Using the generated code - Troubleshooting and debugging.
Make sure that the generated SQL actually retrieve rows at SQLServer. As you are adding relations to the call (Inner relation), maybe the Employees don't have Contact information related to them.
Joined: 25-Nov-2007
Hi, Thanks for the suggestion. I was not enthusiastic about downloading another application and will happily do without the profiler.
Sorry to be so clueless, but when I enabled tracing, I got the output below. As far as I can tell the SQL is not getting processed. I'll look at the relationships in more detail, as you suggested.
Carol
Output from tracing:
'AW.WIN.vshost.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'AW.WIN.vshost.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Utilities\ 8.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Utilities.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'AW.WIN.vshost.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_MSIL\System.Windows.Forms\2.0.0.0__b77a5c561934e089\System.Windows.Forms.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'AW.WIN.vshost.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'AW.WIN.vshost.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_MSIL\System.Drawing\2.0.0.0__b03f5f7f11d50a3a\System.Drawing.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'AW.WIN.vshost.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_MSIL\Microsoft.VisualStudio.HostingProcess.Utilities.Sync\ 8.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualStudio.HostingProcess.Utilities.Sync.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'AW.WIN.vshost.exe' (Managed): Loaded 'C:\Documents and Settings\cgray\My Documents\Visual Studio 2005\Projects\AW\AW.WIN\bin\Debug\AW.WIN.vshost.exe', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'AW.WIN.vshost.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_32\System.Data\2.0.0.0__b77a5c561934e089\System.Data.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'AW.WIN.vshost.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_MSIL\System.Deployment\2.0.0.0__b03f5f7f11d50a3a\System.Deployment.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. 'AW.WIN.vshost.exe' (Managed): Loaded 'C:\WINDOWS\assembly\GAC_MSIL\System.Xml\2.0.0.0__b77a5c561934e089\System.Xml.dll', Skipped loading symbols. Module is optimized and the debugger option 'Just My Code' is enabled. The thread 0x38c has exited with code 0 (0x0). The thread 0x66c has exited with code 0 (0x0). 'AW.WIN.vshost.exe' (Managed): Loaded 'C:\Documents and Settings\cgray\My Documents\Visual Studio 2005\Projects\AW\AW.WIN\bin\Debug\AW.WIN.exe', Symbols loaded. The program '[1096] AW.WIN.vshost.exe: Managed' has exited with code 0 (0x0).
Joined: 25-Nov-2007
Hello, Thanks for your responses. I will check the Troubleshooting and Debugging to see which flags should be set, and will review the entities and their relationships.
And I will post new results, hoping to find a more specific reason that the combo box isn't getting populated. Or better yet, get it working.
Carol
Joined: 25-Nov-2007
Problem solved!
I had manually created the frmOrganization_Load, by directly typing, rather than double clicking on the title bar of the form to create the shell of the method and set up the correct association. Once I recreated this method, by double clicking the title bar and then filling in the lines of code with the DataSource, all was well. (I guess this associates the event of opening the form with the Load method.)
Prior to stumbling on this solution, I had a lot of learning hours, setting debug flags and levels, looking at generated sql and examining the entities and their relationships, so this wasn't entirely a wasted effort.
Hopefully this will be of help to someone else who is new to Windows Forms creation.
And thanks very much for all your suggestions as to what might cause my problem in binding values to display in the drop down combo box.
Carol