New Posts New Posts RSS Feed: Tech Tip: Use ReplaceRange() to Populate Your EntityList
  FAQ FAQ  Forum Search   Calendar   Register Register  Login Login

Tech Tip: Use ReplaceRange() to Populate Your EntityList

 Post Reply Post Reply
Author
IdeaBlade View Drop Down
Moderator Group
Moderator Group
Avatar

Joined: 30-May-2007
Location: United States
Posts: 353
Post Options Post Options   Quote IdeaBlade Quote  Post ReplyReply Direct Link To This Post Topic: Tech Tip: Use ReplaceRange() to Populate Your EntityList
    Posted: 06-Jun-2007 at 1:04pm

Level 100
DevForce Express
January 11, 2007
View%20all%20Tech%20Tips Use ReplaceRange() To Populate Your EntityList

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>())

 

ReplaceRange() clears the old entity references (if there were any) out of the mEmployees list, and repopulates it with the new entity references.  But mEmployees remains the same EntityList; namely, the one we designated to feed the BindingSource.

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!



Edited by IdeaBlade - 09-Jul-2007 at 12:32pm
Back to Top
 Post Reply Post Reply

Forum Jump Forum Permissions View Drop Down