In
the Fundamentals tutorials, you
often see code like the following,
which asks the DevForce PersistenceManager
for some business objects, assigns
them to an EntityList, and then
sets the DataSource of a .NET BindingSource
object to that EntityList:
Listing
1. Load-Then-Configure
|
| |
C#:
private PersistenceManager mPersMgr;
private EntityList<Employee> mEmployees;
private void EmployeeForm_Load(object sender, EventArgs e)
{
mPersMgr = PersistenceManager.DefaultManager;
mEmployees = mPersMgr.GetEntities<Employee>();
this.mEmployeesBS.DataSource
= mEmployees;
}
VB.NET:
Private mPersMgr As PersistenceManager
Private mEmployees As EntityList(Of Employee)
Private Sub EmployeeForm_Load( _
ByVal sender As Object, ByVal e As EventArgs)
mPersMgr = PersistenceManager.DefaultManager
mEmployees = mPersMgr.GetEntities(Of Employee)()
Me.mEmployeesBS.DataSource = mEmployees
End Sub
|
|
The above code works
fine; but suppose we reverse the
order of the two statements that
(1) retrieve the entities, and
(2) configure the BindingSource.
Having done that, the statement
that configures the BindingSource
then won’t work unless we first
instantiate the EntityList, so
we also make that change in the
declaration section.
The
result of those small changes is
shown in Listing 2:
Listing
2. Configure-Then-Load
|
| |
C#:
private PersistenceManager mPersMgr;
private EntityList<Employee> mEmployees
=
new EntityList<Employee>();
private void EmployeeForm_Load(object sender, EventArgs e)
{
mPersMgr = PersistenceManager.DefaultManager;
this.mEmployeesBS.DataSource
= mEmployees;
mEmployees = mPersMgr.GetEntities<Employee>();
}
VB.NET:
Private mPersMgr As PersistenceManager
Private mEmployees As EntityList(Of Employee) = _
New EntityList(Of Employee)()
Private Sub EmployeeForm_Load(ByVal sender As Object,
_
ByVal e As EventArgs)
mPersMgr
= PersistenceManager.DefaultManager
Me.mEmployeesBS.DataSource = mEmployees
mEmployees
= mPersMgr.GetEntities(Of Employee)()
End Sub
|
|
If we were hoping
this new code would produce a collection
of Employees whose property values
would display nicely in bound controls
on our form, we’re in for
a disappointment. At the conclusion
of the above load event handler’s
execution, the BindingSource will
be left managing exactly 0 employees!
We’ll see in a moment
why the revised code fails, but
first let’s discuss why
we might want the revised order.
We can see this most easily with
a bit of refactoring (Listing
3):
Listing 3. Refactored
Configure-Then-Load
|
| |
C#:
private PersistenceManager mPersMgr;
private EntityList<Employee> mEmployees
=
new EntityList<Employee>();
private void EmployeeForm_Load(object sender, EventArgs e)
{
InitializePersistenceManager();
ConfigureBindingSources();
LoadData();
}
private void InitializePersistenceManager() {
mPersMgr = PersistenceManager.DefaultManager;
}
private void ConfigureBindingSources() {
this.mEmployeesBS.DataSource
= mEmployees;
}
private void LoadData() {
mEmployees = mPersMgr.GetEntities<Employee>();
}
VB.NET:
Private mPersMgr As PersistenceManager
Private mEmployees As EntityList(Of Employee) = _
New EntityList(Of Employee)()
Private Sub EmployeeForm_Load(ByVal sender As Object,
_
ByVal e As EventArgs)
InitializePersistenceManager()
ConfigureBindingSources()
LoadData()
End Sub
Private Sub InitializePersistenceManager()
mPersMgr
= PersistenceManager.DefaultManager
End Sub
Private Sub ConfigureBindingSources()
Me.mEmployeesBS.DataSource = mEmployees
End Sub
Private Sub LoadData()
mEmployees
= mPersMgr.GetEntities(Of Employee)()
End Sub
|
|
We have now segregated
into separate methods -- which
are now ready to evolve to accommodate
greater
complexity -- the configuration of our BindingSource(s) from the loading
of data. Furthermore, we’re completing our configuration
before loading any data. Why is this better? Well, for one, it just makes
a certain kind of intuitive sense to finish configuring the form before
loading data into it. For another, there are many situations wherein
the specific set of objects to be loaded depends upon some external condition (as
when loading the Orders for the current Employee, or loading the Employees
for the current CorporateDivision, etc.). It also is often the case,
in such circumstances, that the data must be loaded and reloaded many
times during the form’s (or UserControl’s) lifetime, as those
external conditions change. It seems pointless to redo configuration
steps (like setting the DataSource of a BindingSource) every time the
data is reloaded.
So what was the problem with
our Configure-Then-Load strategy,
as implemented in Listing 2?
Let’s review the sequence
of operations.
First we instantiated our EntityList:
|
| |
C#:
private EntityList<Employee> mEmployees
=
new EntityList<Employee>();
VB.NET:
Private mEmployees As EntityList(Of Employee) = _
New EntityList(Of Employee)()
|
|
| Then we configured
our BindingSource: |
| |
C#:
this.mEmployeesBS.DataSource
= mEmployees;
VB.NET:
Me.mEmployeesBS.DataSource = mEmployees
|
|
Finally we loaded
our data:
|
| |
C#:
mEmployees = mPersMgr.GetEntities<Employee>();
VB.NET:
mEmployees = mPersMgr.GetEntities<Employee>()
|
|
The problem is that
the call to mPersMgr.GetEntities<Employee>() returns a new EntityList,
different from the one instantiated
in the declaration statement. Now this.mEmployeesBS.DataSource is
pointing at the old EntityList,
which was instantiated but not
populated; whereas we just retrieved
Employees into a different EntityList
which we subsequently assigned
to the mEmployees object. This
is just the old business of a sequence
of statements like the following:
| |
X = 2
y = x
x = 3
print y |
where the value printed for
y equals 2, when you were really
hoping it would equal 3!
Fortunately, there’s a
simple solution. Instead of using
the statement
|
| |
C#:
mEmployees = mPersMgr.GetEntities<Employee>();
VB.NET:
mEmployees = mPersMgr.GetEntities<Employee>()
|
|
to retrieve the
employees, use:
|
| |
C#:
mEmployees.ReplaceRange(mPersMgr.GetEntities<Employee>());
VB.NET:
mEmployees.ReplaceRange(mPersMgr.GetEntities<Employee>())
|
|
|
We can go on calling ReplaceRange() repeatedly, as often
as we like, to swap out different
sets of Employees. Bound controls on our form or UserControl will
immediately reflect the new
data each time – no reconfiguration
required!
|